From 33bd307041c4414cfd936ada9fcaa96d3b233ed4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 13:42:01 -0400 Subject: [PATCH 001/333] [splittiming] another attempt, so branch reopened. fork of 848de97 shadows 5ed5cb4 --- src/Makefile.am | 234 ++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 117 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ed823447e0..84c8a1968b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -360,22 +360,22 @@ ScoreDisplayLifeTime.cpp ScoreDisplayLifeTime.h \ ScoreDisplayNormal.cpp ScoreDisplayNormal.h ScoreDisplayOni.cpp ScoreDisplayOni.h \ ScoreDisplayPercentage.cpp ScoreDisplayPercentage.h ScoreDisplayRave.cpp ScoreDisplayRave.h -PCRE = pcre/get.c pcre/internal.h pcre/maketables.c pcre/pcre.c pcre/pcre.h pcre/study.c -EXTRA_DIST += pcre/chartables.c +PCRE = ../extern/pcre/get.c ../extern/pcre/internal.h ../extern/pcre/maketables.c ../extern/pcre/pcre.c ../extern/pcre/pcre.h ../extern/pcre/study.c +EXTRA_DIST += ../extern/pcre/chartables.c -Lua = lua-5.1/src/lapi.c lua-5.1/src/lauxlib.c lua-5.1/src/lbaselib.c lua-5.1/src/lcode.c lua-5.1/src/ldblib.c \ -lua-5.1/src/ldebug.c lua-5.1/src/ldo.c lua-5.1/src/ldump.c lua-5.1/src/lfunc.c lua-5.1/src/lgc.c lua-5.1/src/linit.c \ -lua-5.1/src/liolib.c lua-5.1/src/llex.c lua-5.1/src/lmathlib.c lua-5.1/src/lmem.c lua-5.1/src/loadlib.c \ -lua-5.1/src/lobject.c lua-5.1/src/lopcodes.c lua-5.1/src/loslib.c lua-5.1/src/lparser.c lua-5.1/src/lstate.c \ -lua-5.1/src/lstring.c lua-5.1/src/lstrlib.c lua-5.1/src/ltable.c lua-5.1/src/ltablib.c lua-5.1/src/ltm.c \ -lua-5.1/src/lundump.c lua-5.1/src/lvm.c lua-5.1/src/lzio.c lua-5.1/src/lapi.h lua-5.1/src/lauxlib.h lua-5.1/src/lcode.h \ -lua-5.1/src/ldebug.h lua-5.1/src/ldo.h lua-5.1/src/lfunc.h lua-5.1/src/lgc.h lua-5.1/src/llex.h lua-5.1/src/llimits.h \ -lua-5.1/src/lmem.h lua-5.1/src/lobject.h lua-5.1/src/lopcodes.h lua-5.1/src/lparser.h lua-5.1/src/lstate.h \ -lua-5.1/src/lstring.h lua-5.1/src/ltable.h lua-5.1/src/ltm.h lua-5.1/src/luaconf.h lua-5.1/src/lua.h lua-5.1/src/lualib.h \ -lua-5.1/src/lundump.h lua-5.1/src/lvm.h lua-5.1/src/lzio.h +Lua = ../extern/lua-5.1/src/lapi.c ../extern/lua-5.1/src/lauxlib.c ../extern/lua-5.1/src/lbaselib.c ../extern/lua-5.1/src/lcode.c ../extern/lua-5.1/src/ldblib.c \ +../extern/lua-5.1/src/ldebug.c ../extern/lua-5.1/src/ldo.c ../extern/lua-5.1/src/ldump.c ../extern/lua-5.1/src/lfunc.c ../extern/lua-5.1/src/lgc.c ../extern/lua-5.1/src/linit.c \ +../extern/lua-5.1/src/liolib.c ../extern/lua-5.1/src/llex.c ../extern/lua-5.1/src/lmathlib.c ../extern/lua-5.1/src/lmem.c ../extern/lua-5.1/src/loadlib.c \ +../extern/lua-5.1/src/lobject.c ../extern/lua-5.1/src/lopcodes.c ../extern/lua-5.1/src/loslib.c ../extern/lua-5.1/src/lparser.c ../extern/lua-5.1/src/lstate.c \ +../extern/lua-5.1/src/lstring.c ../extern/lua-5.1/src/lstrlib.c ../extern/lua-5.1/src/ltable.c ../extern/lua-5.1/src/ltablib.c ../extern/lua-5.1/src/ltm.c \ +../extern/lua-5.1/src/lundump.c ../extern/lua-5.1/src/lvm.c ../extern/lua-5.1/src/lzio.c ../extern/lua-5.1/src/lapi.h ../extern/lua-5.1/src/lauxlib.h ../extern/lua-5.1/src/lcode.h \ +../extern/lua-5.1/src/ldebug.h ../extern/lua-5.1/src/ldo.h ../extern/lua-5.1/src/lfunc.h ../extern/lua-5.1/src/lgc.h ../extern/lua-5.1/src/llex.h ../extern/lua-5.1/src/llimits.h \ +../extern/lua-5.1/src/lmem.h ../extern/lua-5.1/src/lobject.h ../extern/lua-5.1/src/lopcodes.h ../extern/lua-5.1/src/lparser.h ../extern/lua-5.1/src/lstate.h \ +../extern/lua-5.1/src/lstring.h ../extern/lua-5.1/src/ltable.h ../extern/lua-5.1/src/ltm.h ../extern/lua-5.1/src/luaconf.h ../extern/lua-5.1/src/lua.h ../extern/lua-5.1/src/lualib.h \ +../extern/lua-5.1/src/lundump.h ../extern/lua-5.1/src/lvm.h ../extern/lua-5.1/src/lzio.h -jsoncpp = jsoncpp/src/lib_json/json_reader.cpp jsoncpp/src/lib_json/json_value.cpp \ -jsoncpp/src/lib_json/json_writer.cpp +jsoncpp = ../extern/jsoncpp/src/lib_json/json_reader.cpp ../extern/jsoncpp/src/lib_json/json_value.cpp \ +../extern/jsoncpp/src/lib_json/json_writer.cpp RageFile = \ RageFileBasic.cpp RageFileBasic.h \ @@ -470,112 +470,112 @@ GlobalSingletons += ezsockets.cpp ezsockets.h endif libtommath_a_SOURCES = \ -libtommath/bncore.c libtommath/bn_mp_init.c libtommath/bn_mp_clear.c libtommath/bn_mp_exch.c libtommath/bn_mp_grow.c libtommath/bn_mp_shrink.c \ -libtommath/bn_mp_clamp.c libtommath/bn_mp_zero.c libtommath/bn_mp_set.c libtommath/bn_mp_set_int.c libtommath/bn_mp_init_size.c libtommath/bn_mp_copy.c \ -libtommath/bn_mp_init_copy.c libtommath/bn_mp_abs.c libtommath/bn_mp_neg.c libtommath/bn_mp_cmp_mag.c libtommath/bn_mp_cmp.c libtommath/bn_mp_cmp_d.c \ -libtommath/bn_mp_rshd.c libtommath/bn_mp_lshd.c libtommath/bn_mp_mod_2d.c libtommath/bn_mp_div_2d.c libtommath/bn_mp_mul_2d.c libtommath/bn_mp_div_2.c \ -libtommath/bn_mp_mul_2.c libtommath/bn_s_mp_add.c libtommath/bn_s_mp_sub.c libtommath/bn_fast_s_mp_mul_digs.c libtommath/bn_s_mp_mul_digs.c \ -libtommath/bn_fast_s_mp_mul_high_digs.c libtommath/bn_s_mp_mul_high_digs.c libtommath/bn_fast_s_mp_sqr.c libtommath/bn_s_mp_sqr.c \ -libtommath/bn_mp_add.c libtommath/bn_mp_sub.c libtommath/bn_mp_karatsuba_mul.c libtommath/bn_mp_mul.c libtommath/bn_mp_karatsuba_sqr.c \ -libtommath/bn_mp_sqr.c libtommath/bn_mp_div.c libtommath/bn_mp_mod.c libtommath/bn_mp_add_d.c libtommath/bn_mp_sub_d.c libtommath/bn_mp_mul_d.c \ -libtommath/bn_mp_div_d.c libtommath/bn_mp_mod_d.c libtommath/bn_mp_expt_d.c libtommath/bn_mp_addmod.c libtommath/bn_mp_submod.c \ -libtommath/bn_mp_mulmod.c libtommath/bn_mp_sqrmod.c libtommath/bn_mp_gcd.c libtommath/bn_mp_lcm.c libtommath/bn_fast_mp_invmod.c libtommath/bn_mp_invmod.c \ -libtommath/bn_mp_reduce.c libtommath/bn_mp_montgomery_setup.c libtommath/bn_fast_mp_montgomery_reduce.c libtommath/bn_mp_montgomery_reduce.c \ -libtommath/bn_mp_exptmod_fast.c libtommath/bn_mp_exptmod.c libtommath/bn_mp_2expt.c libtommath/bn_mp_n_root.c libtommath/bn_mp_jacobi.c libtommath/bn_reverse.c \ -libtommath/bn_mp_count_bits.c libtommath/bn_mp_read_unsigned_bin.c libtommath/bn_mp_read_signed_bin.c libtommath/bn_mp_to_unsigned_bin.c \ -libtommath/bn_mp_to_signed_bin.c libtommath/bn_mp_unsigned_bin_size.c libtommath/bn_mp_signed_bin_size.c \ -libtommath/bn_mp_xor.c libtommath/bn_mp_and.c libtommath/bn_mp_or.c libtommath/bn_mp_rand.c libtommath/bn_mp_montgomery_calc_normalization.c \ -libtommath/bn_mp_prime_is_divisible.c libtommath/bn_prime_tab.c libtommath/bn_mp_prime_fermat.c libtommath/bn_mp_prime_miller_rabin.c \ -libtommath/bn_mp_prime_is_prime.c libtommath/bn_mp_prime_next_prime.c libtommath/bn_mp_dr_reduce.c \ -libtommath/bn_mp_dr_is_modulus.c libtommath/bn_mp_dr_setup.c libtommath/bn_mp_reduce_setup.c \ -libtommath/bn_mp_toom_mul.c libtommath/bn_mp_toom_sqr.c libtommath/bn_mp_div_3.c libtommath/bn_s_mp_exptmod.c \ -libtommath/bn_mp_reduce_2k.c libtommath/bn_mp_reduce_is_2k.c libtommath/bn_mp_reduce_2k_setup.c \ -libtommath/bn_mp_reduce_2k_l.c libtommath/bn_mp_reduce_is_2k_l.c libtommath/bn_mp_reduce_2k_setup_l.c \ -libtommath/bn_mp_radix_smap.c libtommath/bn_mp_read_radix.c libtommath/bn_mp_toradix.c libtommath/bn_mp_radix_size.c \ -libtommath/bn_mp_fread.c libtommath/bn_mp_fwrite.c libtommath/bn_mp_cnt_lsb.c libtommath/bn_error.c \ -libtommath/bn_mp_init_multi.c libtommath/bn_mp_clear_multi.c libtommath/bn_mp_exteuclid.c libtommath/bn_mp_toradix_n.c \ -libtommath/bn_mp_prime_random_ex.c libtommath/bn_mp_get_int.c libtommath/bn_mp_sqrt.c libtommath/bn_mp_is_square.c libtommath/bn_mp_init_set.c \ -libtommath/bn_mp_init_set_int.c libtommath/bn_mp_invmod_slow.c libtommath/bn_mp_prime_rabin_miller_trials.c \ -libtommath/bn_mp_to_signed_bin_n.c libtommath/bn_mp_to_unsigned_bin_n.c \ -libtommath/tommath_class.h libtommath/tommath.h libtommath/tommath_superclass.h -EXTRA_DIST += libtommath/bn_prime_tab.c +../extern/libtommath/bncore.c ../extern/libtommath/bn_mp_init.c ../extern/libtommath/bn_mp_clear.c ../extern/libtommath/bn_mp_exch.c ../extern/libtommath/bn_mp_grow.c ../extern/libtommath/bn_mp_shrink.c \ +../extern/libtommath/bn_mp_clamp.c ../extern/libtommath/bn_mp_zero.c ../extern/libtommath/bn_mp_set.c ../extern/libtommath/bn_mp_set_int.c ../extern/libtommath/bn_mp_init_size.c ../extern/libtommath/bn_mp_copy.c \ +../extern/libtommath/bn_mp_init_copy.c ../extern/libtommath/bn_mp_abs.c ../extern/libtommath/bn_mp_neg.c ../extern/libtommath/bn_mp_cmp_mag.c ../extern/libtommath/bn_mp_cmp.c ../extern/libtommath/bn_mp_cmp_d.c \ +../extern/libtommath/bn_mp_rshd.c ../extern/libtommath/bn_mp_lshd.c ../extern/libtommath/bn_mp_mod_2d.c ../extern/libtommath/bn_mp_div_2d.c ../extern/libtommath/bn_mp_mul_2d.c ../extern/libtommath/bn_mp_div_2.c \ +../extern/libtommath/bn_mp_mul_2.c ../extern/libtommath/bn_s_mp_add.c ../extern/libtommath/bn_s_mp_sub.c ../extern/libtommath/bn_fast_s_mp_mul_digs.c ../extern/libtommath/bn_s_mp_mul_digs.c \ +../extern/libtommath/bn_fast_s_mp_mul_high_digs.c ../extern/libtommath/bn_s_mp_mul_high_digs.c ../extern/libtommath/bn_fast_s_mp_sqr.c ../extern/libtommath/bn_s_mp_sqr.c \ +../extern/libtommath/bn_mp_add.c ../extern/libtommath/bn_mp_sub.c ../extern/libtommath/bn_mp_karatsuba_mul.c ../extern/libtommath/bn_mp_mul.c ../extern/libtommath/bn_mp_karatsuba_sqr.c \ +../extern/libtommath/bn_mp_sqr.c ../extern/libtommath/bn_mp_div.c ../extern/libtommath/bn_mp_mod.c ../extern/libtommath/bn_mp_add_d.c ../extern/libtommath/bn_mp_sub_d.c ../extern/libtommath/bn_mp_mul_d.c \ +../extern/libtommath/bn_mp_div_d.c ../extern/libtommath/bn_mp_mod_d.c ../extern/libtommath/bn_mp_expt_d.c ../extern/libtommath/bn_mp_addmod.c ../extern/libtommath/bn_mp_submod.c \ +../extern/libtommath/bn_mp_mulmod.c ../extern/libtommath/bn_mp_sqrmod.c ../extern/libtommath/bn_mp_gcd.c ../extern/libtommath/bn_mp_lcm.c ../extern/libtommath/bn_fast_mp_invmod.c ../extern/libtommath/bn_mp_invmod.c \ +../extern/libtommath/bn_mp_reduce.c ../extern/libtommath/bn_mp_montgomery_setup.c ../extern/libtommath/bn_fast_mp_montgomery_reduce.c ../extern/libtommath/bn_mp_montgomery_reduce.c \ +../extern/libtommath/bn_mp_exptmod_fast.c ../extern/libtommath/bn_mp_exptmod.c ../extern/libtommath/bn_mp_2expt.c ../extern/libtommath/bn_mp_n_root.c ../extern/libtommath/bn_mp_jacobi.c ../extern/libtommath/bn_reverse.c \ +../extern/libtommath/bn_mp_count_bits.c ../extern/libtommath/bn_mp_read_unsigned_bin.c ../extern/libtommath/bn_mp_read_signed_bin.c ../extern/libtommath/bn_mp_to_unsigned_bin.c \ +../extern/libtommath/bn_mp_to_signed_bin.c ../extern/libtommath/bn_mp_unsigned_bin_size.c ../extern/libtommath/bn_mp_signed_bin_size.c \ +../extern/libtommath/bn_mp_xor.c ../extern/libtommath/bn_mp_and.c ../extern/libtommath/bn_mp_or.c ../extern/libtommath/bn_mp_rand.c ../extern/libtommath/bn_mp_montgomery_calc_normalization.c \ +../extern/libtommath/bn_mp_prime_is_divisible.c ../extern/libtommath/bn_prime_tab.c ../extern/libtommath/bn_mp_prime_fermat.c ../extern/libtommath/bn_mp_prime_miller_rabin.c \ +../extern/libtommath/bn_mp_prime_is_prime.c ../extern/libtommath/bn_mp_prime_next_prime.c ../extern/libtommath/bn_mp_dr_reduce.c \ +../extern/libtommath/bn_mp_dr_is_modulus.c ../extern/libtommath/bn_mp_dr_setup.c ../extern/libtommath/bn_mp_reduce_setup.c \ +../extern/libtommath/bn_mp_toom_mul.c ../extern/libtommath/bn_mp_toom_sqr.c ../extern/libtommath/bn_mp_div_3.c ../extern/libtommath/bn_s_mp_exptmod.c \ +../extern/libtommath/bn_mp_reduce_2k.c ../extern/libtommath/bn_mp_reduce_is_2k.c ../extern/libtommath/bn_mp_reduce_2k_setup.c \ +../extern/libtommath/bn_mp_reduce_2k_l.c ../extern/libtommath/bn_mp_reduce_is_2k_l.c ../extern/libtommath/bn_mp_reduce_2k_setup_l.c \ +../extern/libtommath/bn_mp_radix_smap.c ../extern/libtommath/bn_mp_read_radix.c ../extern/libtommath/bn_mp_toradix.c ../extern/libtommath/bn_mp_radix_size.c \ +../extern/libtommath/bn_mp_fread.c ../extern/libtommath/bn_mp_fwrite.c ../extern/libtommath/bn_mp_cnt_lsb.c ../extern/libtommath/bn_error.c \ +../extern/libtommath/bn_mp_init_multi.c ../extern/libtommath/bn_mp_clear_multi.c ../extern/libtommath/bn_mp_exteuclid.c ../extern/libtommath/bn_mp_toradix_n.c \ +../extern/libtommath/bn_mp_prime_random_ex.c ../extern/libtommath/bn_mp_get_int.c ../extern/libtommath/bn_mp_sqrt.c ../extern/libtommath/bn_mp_is_square.c ../extern/libtommath/bn_mp_init_set.c \ +../extern/libtommath/bn_mp_init_set_int.c ../extern/libtommath/bn_mp_invmod_slow.c ../extern/libtommath/bn_mp_prime_rabin_miller_trials.c \ +../extern/libtommath/bn_mp_to_signed_bin_n.c ../extern/libtommath/bn_mp_to_unsigned_bin_n.c \ +../extern/libtommath/tommath_class.h ../extern/libtommath/tommath.h ../extern/libtommath/tommath_superclass.h +EXTRA_DIST += ../extern/libtommath/bn_prime_tab.c -libtommath_a_CPPFLAGS = -I$(srcdir)/libtommath $(AM_CPPFLAGS) +libtommath_a_CPPFLAGS = -I$(srcdir)/../extern/libtommath $(AM_CPPFLAGS) noinst_LIBRARIES += libtommath.a libtomcrypt_a_SOURCES = \ -libtomcrypt/src/ciphers/aes/aes.c \ -libtomcrypt/src/hashes/md5.c libtomcrypt/src/hashes/sha1.c libtomcrypt/src/hashes/helper/hash_memory.c \ -libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c libtomcrypt/src/math/ltm_desc.c libtomcrypt/src/math/multi.c \ -libtomcrypt/src/math/rand_prime.c libtomcrypt/src/misc/base64/base64_decode.c \ -libtomcrypt/src/misc/base64/base64_encode.c libtomcrypt/src/misc/burn_stack.c libtomcrypt/src/misc/crypt/crypt.c \ -libtomcrypt/src/misc/crypt/crypt_argchk.c libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c \ -libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c libtomcrypt/src/misc/crypt/crypt_find_cipher.c \ -libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c \ -libtomcrypt/src/misc/crypt/crypt_find_hash.c libtomcrypt/src/misc/crypt/crypt_find_hash_any.c \ -libtomcrypt/src/misc/crypt/crypt_find_hash_id.c libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c \ -libtomcrypt/src/misc/crypt/crypt_find_prng.c libtomcrypt/src/misc/crypt/crypt_fsa.c libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c \ -libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c \ -libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c \ -libtomcrypt/src/misc/crypt/crypt_register_cipher.c libtomcrypt/src/misc/crypt/crypt_register_hash.c \ -libtomcrypt/src/misc/crypt/crypt_register_prng.c libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c \ -libtomcrypt/src/misc/crypt/crypt_unregister_hash.c libtomcrypt/src/misc/crypt/crypt_unregister_prng.c \ -libtomcrypt/src/misc/error_to_string.c libtomcrypt/src/misc/pkcs5/pkcs_5_1.c libtomcrypt/src/misc/pkcs5/pkcs_5_2.c libtomcrypt/src/misc/zeromem.c \ -libtomcrypt/src/modes/cbc/cbc_decrypt.c libtomcrypt/src/modes/cbc/cbc_done.c libtomcrypt/src/modes/cbc/cbc_encrypt.c \ -libtomcrypt/src/modes/cbc/cbc_getiv.c libtomcrypt/src/modes/cbc/cbc_setiv.c libtomcrypt/src/modes/cbc/cbc_start.c \ -libtomcrypt/src/modes/cfb/cfb_decrypt.c libtomcrypt/src/modes/cfb/cfb_done.c libtomcrypt/src/modes/cfb/cfb_encrypt.c \ -libtomcrypt/src/modes/cfb/cfb_getiv.c libtomcrypt/src/modes/cfb/cfb_setiv.c libtomcrypt/src/modes/cfb/cfb_start.c \ -libtomcrypt/src/modes/ctr/ctr_decrypt.c libtomcrypt/src/modes/ctr/ctr_done.c libtomcrypt/src/modes/ctr/ctr_encrypt.c \ -libtomcrypt/src/modes/ctr/ctr_getiv.c libtomcrypt/src/modes/ctr/ctr_setiv.c libtomcrypt/src/modes/ctr/ctr_start.c libtomcrypt/src/modes/ctr/ctr_test.c \ -libtomcrypt/src/modes/ecb/ecb_decrypt.c libtomcrypt/src/modes/ecb/ecb_done.c libtomcrypt/src/modes/ecb/ecb_encrypt.c \ -libtomcrypt/src/modes/ecb/ecb_start.c \ -libtomcrypt/src/modes/ofb/ofb_decrypt.c libtomcrypt/src/modes/ofb/ofb_done.c \ -libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c \ -libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c \ -libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c \ -libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c \ -libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c \ -libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c \ -libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c \ -libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c \ -libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c \ -libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c \ -libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c \ -libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c \ -libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c \ -libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c \ -libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c \ -libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c libtomcrypt/src/pk/asn1/der/set/der_encode_set.c \ -libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c \ -libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c \ -libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c \ -libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c \ -libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c \ -libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c libtomcrypt/src/pk/dsa/dsa_decrypt_key.c \ -libtomcrypt/src/pk/dsa/dsa_encrypt_key.c libtomcrypt/src/pk/dsa/dsa_export.c libtomcrypt/src/pk/dsa/dsa_free.c libtomcrypt/src/pk/dsa/dsa_import.c \ -libtomcrypt/src/pk/dsa/dsa_make_key.c libtomcrypt/src/pk/dsa/dsa_shared_secret.c libtomcrypt/src/pk/dsa/dsa_sign_hash.c \ -libtomcrypt/src/pk/dsa/dsa_verify_hash.c libtomcrypt/src/pk/dsa/dsa_verify_key.c \ -libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c \ -libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c \ -libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c \ -libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c libtomcrypt/src/pk/rsa/rsa_decrypt_key.c libtomcrypt/src/pk/rsa/rsa_encrypt_key.c \ -libtomcrypt/src/pk/rsa/rsa_export.c libtomcrypt/src/pk/rsa/rsa_exptmod.c libtomcrypt/src/pk/rsa/rsa_free.c libtomcrypt/src/pk/rsa/rsa_import.c \ -libtomcrypt/src/pk/rsa/rsa_make_key.c libtomcrypt/src/pk/rsa/rsa_sign_hash.c libtomcrypt/src/pk/rsa/rsa_verify_hash.c libtomcrypt/src/prngs/fortuna.c \ -libtomcrypt/src/prngs/rng_get_bytes.c libtomcrypt/src/prngs/rng_make_prng.c \ -libtomcrypt/src/prngs/sprng.c libtomcrypt/src/prngs/yarrow.c \ -libtomcrypt/src/headers/tomcrypt_argchk.h libtomcrypt/src/headers/tomcrypt_cfg.h libtomcrypt/src/headers/tomcrypt_cipher.h \ -libtomcrypt/src/headers/tomcrypt_custom.h libtomcrypt/src/headers/tomcrypt.h libtomcrypt/src/headers/tomcrypt_hash.h \ -libtomcrypt/src/headers/tomcrypt_mac.h libtomcrypt/src/headers/tomcrypt_macros.h libtomcrypt/src/headers/tomcrypt_math.h \ -libtomcrypt/src/headers/tomcrypt_misc.h libtomcrypt/src/headers/tomcrypt_pkcs.h libtomcrypt/src/headers/tomcrypt_pk.h \ -libtomcrypt/src/headers/tomcrypt_prng.h -EXTRA_DIST += libtomcrypt/src/ciphers/aes/aes_tab.c libtomcrypt/src/prngs/sober128tab.c +../extern/libtomcrypt/src/ciphers/aes/aes.c \ +../extern/libtomcrypt/src/hashes/md5.c ../extern/libtomcrypt/src/hashes/sha1.c ../extern/libtomcrypt/src/hashes/helper/hash_memory.c \ +../extern/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c ../extern/libtomcrypt/src/math/ltm_desc.c ../extern/libtomcrypt/src/math/multi.c \ +../extern/libtomcrypt/src/math/rand_prime.c ../extern/libtomcrypt/src/misc/base64/base64_decode.c \ +../extern/libtomcrypt/src/misc/base64/base64_encode.c ../extern/libtomcrypt/src/misc/burn_stack.c ../extern/libtomcrypt/src/misc/crypt/crypt.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_argchk.c ../extern/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_find_hash.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_find_prng.c ../extern/libtomcrypt/src/misc/crypt/crypt_fsa.c ../extern/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c ../extern/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c ../extern/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_register_cipher.c ../extern/libtomcrypt/src/misc/crypt/crypt_register_hash.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_register_prng.c ../extern/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c \ +../extern/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c ../extern/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c \ +../extern/libtomcrypt/src/misc/error_to_string.c ../extern/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c ../extern/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c ../extern/libtomcrypt/src/misc/zeromem.c \ +../extern/libtomcrypt/src/modes/cbc/cbc_decrypt.c ../extern/libtomcrypt/src/modes/cbc/cbc_done.c ../extern/libtomcrypt/src/modes/cbc/cbc_encrypt.c \ +../extern/libtomcrypt/src/modes/cbc/cbc_getiv.c ../extern/libtomcrypt/src/modes/cbc/cbc_setiv.c ../extern/libtomcrypt/src/modes/cbc/cbc_start.c \ +../extern/libtomcrypt/src/modes/cfb/cfb_decrypt.c ../extern/libtomcrypt/src/modes/cfb/cfb_done.c ../extern/libtomcrypt/src/modes/cfb/cfb_encrypt.c \ +../extern/libtomcrypt/src/modes/cfb/cfb_getiv.c ../extern/libtomcrypt/src/modes/cfb/cfb_setiv.c ../extern/libtomcrypt/src/modes/cfb/cfb_start.c \ +../extern/libtomcrypt/src/modes/ctr/ctr_decrypt.c ../extern/libtomcrypt/src/modes/ctr/ctr_done.c ../extern/libtomcrypt/src/modes/ctr/ctr_encrypt.c \ +../extern/libtomcrypt/src/modes/ctr/ctr_getiv.c ../extern/libtomcrypt/src/modes/ctr/ctr_setiv.c ../extern/libtomcrypt/src/modes/ctr/ctr_start.c ../extern/libtomcrypt/src/modes/ctr/ctr_test.c \ +../extern/libtomcrypt/src/modes/ecb/ecb_decrypt.c ../extern/libtomcrypt/src/modes/ecb/ecb_done.c ../extern/libtomcrypt/src/modes/ecb/ecb_encrypt.c \ +../extern/libtomcrypt/src/modes/ecb/ecb_start.c \ +../extern/libtomcrypt/src/modes/ofb/ofb_decrypt.c ../extern/libtomcrypt/src/modes/ofb/ofb_done.c \ +../extern/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c ../extern/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c ../extern/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c \ +../extern/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c ../extern/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c \ +../extern/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c ../extern/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c ../extern/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c \ +../extern/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c ../extern/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c \ +../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c \ +../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c \ +../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c \ +../extern/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c ../extern/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c ../extern/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c \ +../extern/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c ../extern/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c \ +../extern/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c ../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c \ +../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c \ +../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c ../extern/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c \ +../extern/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c ../extern/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c \ +../extern/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c ../extern/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c \ +../extern/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c ../extern/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c \ +../extern/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c ../extern/libtomcrypt/src/pk/dsa/dsa_export.c ../extern/libtomcrypt/src/pk/dsa/dsa_free.c ../extern/libtomcrypt/src/pk/dsa/dsa_import.c \ +../extern/libtomcrypt/src/pk/dsa/dsa_make_key.c ../extern/libtomcrypt/src/pk/dsa/dsa_shared_secret.c ../extern/libtomcrypt/src/pk/dsa/dsa_sign_hash.c \ +../extern/libtomcrypt/src/pk/dsa/dsa_verify_hash.c ../extern/libtomcrypt/src/pk/dsa/dsa_verify_key.c \ +../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c \ +../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c \ +../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c \ +../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c ../extern/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c ../extern/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c \ +../extern/libtomcrypt/src/pk/rsa/rsa_export.c ../extern/libtomcrypt/src/pk/rsa/rsa_exptmod.c ../extern/libtomcrypt/src/pk/rsa/rsa_free.c ../extern/libtomcrypt/src/pk/rsa/rsa_import.c \ +../extern/libtomcrypt/src/pk/rsa/rsa_make_key.c ../extern/libtomcrypt/src/pk/rsa/rsa_sign_hash.c ../extern/libtomcrypt/src/pk/rsa/rsa_verify_hash.c ../extern/libtomcrypt/src/prngs/fortuna.c \ +../extern/libtomcrypt/src/prngs/rng_get_bytes.c ../extern/libtomcrypt/src/prngs/rng_make_prng.c \ +../extern/libtomcrypt/src/prngs/sprng.c ../extern/libtomcrypt/src/prngs/yarrow.c \ +../extern/libtomcrypt/src/headers/tomcrypt_argchk.h ../extern/libtomcrypt/src/headers/tomcrypt_cfg.h ../extern/libtomcrypt/src/headers/tomcrypt_cipher.h \ +../extern/libtomcrypt/src/headers/tomcrypt_custom.h ../extern/libtomcrypt/src/headers/tomcrypt.h ../extern/libtomcrypt/src/headers/tomcrypt_hash.h \ +../extern/libtomcrypt/src/headers/tomcrypt_mac.h ../extern/libtomcrypt/src/headers/tomcrypt_macros.h ../extern/libtomcrypt/src/headers/tomcrypt_math.h \ +../extern/libtomcrypt/src/headers/tomcrypt_misc.h ../extern/libtomcrypt/src/headers/tomcrypt_pkcs.h ../extern/libtomcrypt/src/headers/tomcrypt_pk.h \ +../extern/libtomcrypt/src/headers/tomcrypt_prng.h +EXTRA_DIST += ../extern/libtomcrypt/src/ciphers/aes/aes_tab.c ../extern/libtomcrypt/src/prngs/sober128tab.c -libtomcrypt_a_CPPFLAGS = -I$(srcdir)/libtomcrypt/src/headers $(AM_CPPFLAGS) +libtomcrypt_a_CPPFLAGS = -I$(srcdir)/../extern/libtomcrypt/src/headers $(AM_CPPFLAGS) noinst_LIBRARIES += libtomcrypt.a @@ -602,10 +602,10 @@ stepmania_LDADD = $(main_LDADD) if BUILD_LUA_BINARIES noinst_PROGRAMS += lua luac -lua_SOURCES = $(Lua) lua-5.1/src/lua.c +lua_SOURCES = $(Lua) ../extern/lua-5.1/src/lua.c lua_LDADD = -lreadline -luac_SOURCES = $(Lua) lua-5.1/src/luac.c lua-5.1/src/print.c +luac_SOURCES = $(Lua) ../extern/lua-5.1/src/luac.c ../extern/lua-5.1/src/print.c luac_LDADD = endif From 94f112e9233d1b21f3ffbb109d6a1a9fe8c380ba Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sun, 8 May 2011 00:58:03 +0700 Subject: [PATCH 002/333] [timingdata] Let's break things! (for now) --- src/Song.h | 5 ++++- src/Steps.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Song.h b/src/Song.h index 9c105a5732..4858080d1a 100644 --- a/src/Song.h +++ b/src/Song.h @@ -284,7 +284,10 @@ public: bool Matches(RString sGroup, RString sSong) const; /** @brief The Song's TimingData. */ - TimingData m_Timing; + TimingData m_SongTiming; + + /** @brief The initial offset of a song. */ + float m_fBeat0OffsetInSeconds; typedef vector VBackgroundChange; private: diff --git a/src/Steps.h b/src/Steps.h index fee6204527..5ffb2b625c 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -31,6 +31,9 @@ public: /** @brief Destroy the Steps that are no longer needed. */ ~Steps(); + /** @brief Timing data */ + TimingData m_SongTiming; + // initializers void AutogenFrom( const Steps *parent, StepsType ntTo ); void CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ); From 0e1843ff8049791f071cb1f868b591af225a0644 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sun, 8 May 2011 01:15:25 +0700 Subject: [PATCH 003/333] [splittiming] 919 errors => 236 errors --- src/Song.h | 29 ++++++++++++++++++++++++++++- src/Steps.h | 8 +++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Song.h b/src/Song.h index 4858080d1a..da2835c79f 100644 --- a/src/Song.h +++ b/src/Song.h @@ -8,9 +8,9 @@ #include "RageUtil_AutoPtr.h" #include "RageUtil_CachedObject.h" #include "RageTypes.h" +#include "Steps.h" #include -class Steps; class Style; class StepsID; struct lua_State; @@ -319,9 +319,11 @@ public: * This must be sorted before gameplay. */ vector m_LyricSegments; +/* [splittiming] void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); } void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); } void AddWarpSegment( const WarpSegment &seg ) { m_Timing.AddWarpSegment( seg ); } +*/ void AddBackgroundChange( BackgroundLayer blLayer, BackgroundChange seg ); void AddForegroundChange( BackgroundChange seg ); void AddLyricSegment( LyricSegment seg ); @@ -329,18 +331,43 @@ public: void GetDisplayBpms( DisplayBpms &AddTo ) const; const BackgroundChange &GetBackgroundAtBeat( BackgroundLayer iLayer, float fBeat ) const; +/* [splittiming] float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); } void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); } BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); } +*/ + /** * @brief Retrieve the beat based on the specified time. * @param fElapsedTime the amount of time since the Song started. * @return the appropriate beat. */ float GetBeatFromElapsedTime( float fElapsedTime ) const + { + return m_SongTiming.GetBeatFromElapsedTime( fElapsedTime ); + } + float GetBeatFromElapsedTime( float fElapsedTime, const Steps &steps ) const + { + return steps.m_Timing.GetBeatFromElapsedTime( fElapsedTime ); + } + + float GetElapsedTimeFromBeat( float fBeat ) const + { + return m_SongTiming.GetElapsedTimeFromBeat( fBeat ); + } + float GetElapsedTimeFromBeat( float fBeat, const Steps &steps ) const + { + return steps.m_Timing.GetElapsedTimeFromBeat( fBeat ); + } + + + /* [splittiming] + float GetBeatFromElapsedTime( float fElapsedTime ) const { return m_Timing.GetBeatFromElapsedTime( fElapsedTime ); } float GetElapsedTimeFromBeat( float fBeat ) const { return m_Timing.GetElapsedTimeFromBeat( fBeat ); } + */ + bool HasSignificantBpmChangesOrStops() const; float GetStepsSeconds() const; bool IsLong() const; diff --git a/src/Steps.h b/src/Steps.h index 5ffb2b625c..e796f99847 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -8,6 +8,8 @@ #include "Difficulty.h" #include "RageUtil_AutoPtr.h" #include "RageUtil_CachedObject.h" +#include "TimingData.h" + class Profile; class NoteData; struct lua_State; @@ -31,9 +33,6 @@ public: /** @brief Destroy the Steps that are no longer needed. */ ~Steps(); - /** @brief Timing data */ - TimingData m_SongTiming; - // initializers void AutogenFrom( const Steps *parent, StepsType ntTo ); void CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ); @@ -119,6 +118,9 @@ public: void TidyUpData(); void CalculateRadarValues( float fMusicLengthSeconds ); + /** @brief Timing data */ + TimingData m_Timing; + // Lua void PushSelf( lua_State *L ); From 40651800f0c572a49e8500ac83783d827650eb03 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sun, 8 May 2011 01:20:58 +0700 Subject: [PATCH 004/333] [splittiming] temporarily rename these functions to make sure that we don't call the wrong one. after it's settled we can rename it back. --- src/Song.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Song.h b/src/Song.h index da2835c79f..2b6769566f 100644 --- a/src/Song.h +++ b/src/Song.h @@ -341,20 +341,20 @@ public: * @brief Retrieve the beat based on the specified time. * @param fElapsedTime the amount of time since the Song started. * @return the appropriate beat. */ - float GetBeatFromElapsedTime( float fElapsedTime ) const + float SongGetBeatFromElapsedTime( float fElapsedTime ) const { return m_SongTiming.GetBeatFromElapsedTime( fElapsedTime ); } - float GetBeatFromElapsedTime( float fElapsedTime, const Steps &steps ) const + float StepsGetBeatFromElapsedTime( float fElapsedTime, const Steps &steps ) const { return steps.m_Timing.GetBeatFromElapsedTime( fElapsedTime ); } - float GetElapsedTimeFromBeat( float fBeat ) const + float SongGetElapsedTimeFromBeat( float fBeat ) const { return m_SongTiming.GetElapsedTimeFromBeat( fBeat ); } - float GetElapsedTimeFromBeat( float fBeat, const Steps &steps ) const + float StepsGetElapsedTimeFromBeat( float fBeat, const Steps &steps ) const { return steps.m_Timing.GetElapsedTimeFromBeat( fBeat ); } From ac9d938cb40b333d680ac5a2d1b94be171680ca4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 14:37:06 -0400 Subject: [PATCH 005/333] Right, never moved libtom* yet. --- src/Makefile.am | 202 ++++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 84c8a1968b..7bdc63a243 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -470,112 +470,112 @@ GlobalSingletons += ezsockets.cpp ezsockets.h endif libtommath_a_SOURCES = \ -../extern/libtommath/bncore.c ../extern/libtommath/bn_mp_init.c ../extern/libtommath/bn_mp_clear.c ../extern/libtommath/bn_mp_exch.c ../extern/libtommath/bn_mp_grow.c ../extern/libtommath/bn_mp_shrink.c \ -../extern/libtommath/bn_mp_clamp.c ../extern/libtommath/bn_mp_zero.c ../extern/libtommath/bn_mp_set.c ../extern/libtommath/bn_mp_set_int.c ../extern/libtommath/bn_mp_init_size.c ../extern/libtommath/bn_mp_copy.c \ -../extern/libtommath/bn_mp_init_copy.c ../extern/libtommath/bn_mp_abs.c ../extern/libtommath/bn_mp_neg.c ../extern/libtommath/bn_mp_cmp_mag.c ../extern/libtommath/bn_mp_cmp.c ../extern/libtommath/bn_mp_cmp_d.c \ -../extern/libtommath/bn_mp_rshd.c ../extern/libtommath/bn_mp_lshd.c ../extern/libtommath/bn_mp_mod_2d.c ../extern/libtommath/bn_mp_div_2d.c ../extern/libtommath/bn_mp_mul_2d.c ../extern/libtommath/bn_mp_div_2.c \ -../extern/libtommath/bn_mp_mul_2.c ../extern/libtommath/bn_s_mp_add.c ../extern/libtommath/bn_s_mp_sub.c ../extern/libtommath/bn_fast_s_mp_mul_digs.c ../extern/libtommath/bn_s_mp_mul_digs.c \ -../extern/libtommath/bn_fast_s_mp_mul_high_digs.c ../extern/libtommath/bn_s_mp_mul_high_digs.c ../extern/libtommath/bn_fast_s_mp_sqr.c ../extern/libtommath/bn_s_mp_sqr.c \ -../extern/libtommath/bn_mp_add.c ../extern/libtommath/bn_mp_sub.c ../extern/libtommath/bn_mp_karatsuba_mul.c ../extern/libtommath/bn_mp_mul.c ../extern/libtommath/bn_mp_karatsuba_sqr.c \ -../extern/libtommath/bn_mp_sqr.c ../extern/libtommath/bn_mp_div.c ../extern/libtommath/bn_mp_mod.c ../extern/libtommath/bn_mp_add_d.c ../extern/libtommath/bn_mp_sub_d.c ../extern/libtommath/bn_mp_mul_d.c \ -../extern/libtommath/bn_mp_div_d.c ../extern/libtommath/bn_mp_mod_d.c ../extern/libtommath/bn_mp_expt_d.c ../extern/libtommath/bn_mp_addmod.c ../extern/libtommath/bn_mp_submod.c \ -../extern/libtommath/bn_mp_mulmod.c ../extern/libtommath/bn_mp_sqrmod.c ../extern/libtommath/bn_mp_gcd.c ../extern/libtommath/bn_mp_lcm.c ../extern/libtommath/bn_fast_mp_invmod.c ../extern/libtommath/bn_mp_invmod.c \ -../extern/libtommath/bn_mp_reduce.c ../extern/libtommath/bn_mp_montgomery_setup.c ../extern/libtommath/bn_fast_mp_montgomery_reduce.c ../extern/libtommath/bn_mp_montgomery_reduce.c \ -../extern/libtommath/bn_mp_exptmod_fast.c ../extern/libtommath/bn_mp_exptmod.c ../extern/libtommath/bn_mp_2expt.c ../extern/libtommath/bn_mp_n_root.c ../extern/libtommath/bn_mp_jacobi.c ../extern/libtommath/bn_reverse.c \ -../extern/libtommath/bn_mp_count_bits.c ../extern/libtommath/bn_mp_read_unsigned_bin.c ../extern/libtommath/bn_mp_read_signed_bin.c ../extern/libtommath/bn_mp_to_unsigned_bin.c \ -../extern/libtommath/bn_mp_to_signed_bin.c ../extern/libtommath/bn_mp_unsigned_bin_size.c ../extern/libtommath/bn_mp_signed_bin_size.c \ -../extern/libtommath/bn_mp_xor.c ../extern/libtommath/bn_mp_and.c ../extern/libtommath/bn_mp_or.c ../extern/libtommath/bn_mp_rand.c ../extern/libtommath/bn_mp_montgomery_calc_normalization.c \ -../extern/libtommath/bn_mp_prime_is_divisible.c ../extern/libtommath/bn_prime_tab.c ../extern/libtommath/bn_mp_prime_fermat.c ../extern/libtommath/bn_mp_prime_miller_rabin.c \ -../extern/libtommath/bn_mp_prime_is_prime.c ../extern/libtommath/bn_mp_prime_next_prime.c ../extern/libtommath/bn_mp_dr_reduce.c \ -../extern/libtommath/bn_mp_dr_is_modulus.c ../extern/libtommath/bn_mp_dr_setup.c ../extern/libtommath/bn_mp_reduce_setup.c \ -../extern/libtommath/bn_mp_toom_mul.c ../extern/libtommath/bn_mp_toom_sqr.c ../extern/libtommath/bn_mp_div_3.c ../extern/libtommath/bn_s_mp_exptmod.c \ -../extern/libtommath/bn_mp_reduce_2k.c ../extern/libtommath/bn_mp_reduce_is_2k.c ../extern/libtommath/bn_mp_reduce_2k_setup.c \ -../extern/libtommath/bn_mp_reduce_2k_l.c ../extern/libtommath/bn_mp_reduce_is_2k_l.c ../extern/libtommath/bn_mp_reduce_2k_setup_l.c \ -../extern/libtommath/bn_mp_radix_smap.c ../extern/libtommath/bn_mp_read_radix.c ../extern/libtommath/bn_mp_toradix.c ../extern/libtommath/bn_mp_radix_size.c \ -../extern/libtommath/bn_mp_fread.c ../extern/libtommath/bn_mp_fwrite.c ../extern/libtommath/bn_mp_cnt_lsb.c ../extern/libtommath/bn_error.c \ -../extern/libtommath/bn_mp_init_multi.c ../extern/libtommath/bn_mp_clear_multi.c ../extern/libtommath/bn_mp_exteuclid.c ../extern/libtommath/bn_mp_toradix_n.c \ -../extern/libtommath/bn_mp_prime_random_ex.c ../extern/libtommath/bn_mp_get_int.c ../extern/libtommath/bn_mp_sqrt.c ../extern/libtommath/bn_mp_is_square.c ../extern/libtommath/bn_mp_init_set.c \ -../extern/libtommath/bn_mp_init_set_int.c ../extern/libtommath/bn_mp_invmod_slow.c ../extern/libtommath/bn_mp_prime_rabin_miller_trials.c \ -../extern/libtommath/bn_mp_to_signed_bin_n.c ../extern/libtommath/bn_mp_to_unsigned_bin_n.c \ -../extern/libtommath/tommath_class.h ../extern/libtommath/tommath.h ../extern/libtommath/tommath_superclass.h -EXTRA_DIST += ../extern/libtommath/bn_prime_tab.c +libtommath/bncore.c libtommath/bn_mp_init.c libtommath/bn_mp_clear.c libtommath/bn_mp_exch.c libtommath/bn_mp_grow.c libtommath/bn_mp_shrink.c \ +libtommath/bn_mp_clamp.c libtommath/bn_mp_zero.c libtommath/bn_mp_set.c libtommath/bn_mp_set_int.c libtommath/bn_mp_init_size.c libtommath/bn_mp_copy.c \ +libtommath/bn_mp_init_copy.c libtommath/bn_mp_abs.c libtommath/bn_mp_neg.c libtommath/bn_mp_cmp_mag.c libtommath/bn_mp_cmp.c libtommath/bn_mp_cmp_d.c \ +libtommath/bn_mp_rshd.c libtommath/bn_mp_lshd.c libtommath/bn_mp_mod_2d.c libtommath/bn_mp_div_2d.c libtommath/bn_mp_mul_2d.c libtommath/bn_mp_div_2.c \ +libtommath/bn_mp_mul_2.c libtommath/bn_s_mp_add.c libtommath/bn_s_mp_sub.c libtommath/bn_fast_s_mp_mul_digs.c libtommath/bn_s_mp_mul_digs.c \ +libtommath/bn_fast_s_mp_mul_high_digs.c libtommath/bn_s_mp_mul_high_digs.c libtommath/bn_fast_s_mp_sqr.c libtommath/bn_s_mp_sqr.c \ +libtommath/bn_mp_add.c libtommath/bn_mp_sub.c libtommath/bn_mp_karatsuba_mul.c libtommath/bn_mp_mul.c libtommath/bn_mp_karatsuba_sqr.c \ +libtommath/bn_mp_sqr.c libtommath/bn_mp_div.c libtommath/bn_mp_mod.c libtommath/bn_mp_add_d.c libtommath/bn_mp_sub_d.c libtommath/bn_mp_mul_d.c \ +libtommath/bn_mp_div_d.c libtommath/bn_mp_mod_d.c libtommath/bn_mp_expt_d.c libtommath/bn_mp_addmod.c libtommath/bn_mp_submod.c \ +libtommath/bn_mp_mulmod.c libtommath/bn_mp_sqrmod.c libtommath/bn_mp_gcd.c libtommath/bn_mp_lcm.c libtommath/bn_fast_mp_invmod.c libtommath/bn_mp_invmod.c \ +libtommath/bn_mp_reduce.c libtommath/bn_mp_montgomery_setup.c libtommath/bn_fast_mp_montgomery_reduce.c libtommath/bn_mp_montgomery_reduce.c \ +libtommath/bn_mp_exptmod_fast.c libtommath/bn_mp_exptmod.c libtommath/bn_mp_2expt.c libtommath/bn_mp_n_root.c libtommath/bn_mp_jacobi.c libtommath/bn_reverse.c \ +libtommath/bn_mp_count_bits.c libtommath/bn_mp_read_unsigned_bin.c libtommath/bn_mp_read_signed_bin.c libtommath/bn_mp_to_unsigned_bin.c \ +libtommath/bn_mp_to_signed_bin.c libtommath/bn_mp_unsigned_bin_size.c libtommath/bn_mp_signed_bin_size.c \ +libtommath/bn_mp_xor.c libtommath/bn_mp_and.c libtommath/bn_mp_or.c libtommath/bn_mp_rand.c libtommath/bn_mp_montgomery_calc_normalization.c \ +libtommath/bn_mp_prime_is_divisible.c libtommath/bn_prime_tab.c libtommath/bn_mp_prime_fermat.c libtommath/bn_mp_prime_miller_rabin.c \ +libtommath/bn_mp_prime_is_prime.c libtommath/bn_mp_prime_next_prime.c libtommath/bn_mp_dr_reduce.c \ +libtommath/bn_mp_dr_is_modulus.c libtommath/bn_mp_dr_setup.c libtommath/bn_mp_reduce_setup.c \ +libtommath/bn_mp_toom_mul.c libtommath/bn_mp_toom_sqr.c libtommath/bn_mp_div_3.c libtommath/bn_s_mp_exptmod.c \ +libtommath/bn_mp_reduce_2k.c libtommath/bn_mp_reduce_is_2k.c libtommath/bn_mp_reduce_2k_setup.c \ +libtommath/bn_mp_reduce_2k_l.c libtommath/bn_mp_reduce_is_2k_l.c libtommath/bn_mp_reduce_2k_setup_l.c \ +libtommath/bn_mp_radix_smap.c libtommath/bn_mp_read_radix.c libtommath/bn_mp_toradix.c libtommath/bn_mp_radix_size.c \ +libtommath/bn_mp_fread.c libtommath/bn_mp_fwrite.c libtommath/bn_mp_cnt_lsb.c libtommath/bn_error.c \ +libtommath/bn_mp_init_multi.c libtommath/bn_mp_clear_multi.c libtommath/bn_mp_exteuclid.c libtommath/bn_mp_toradix_n.c \ +libtommath/bn_mp_prime_random_ex.c libtommath/bn_mp_get_int.c libtommath/bn_mp_sqrt.c libtommath/bn_mp_is_square.c libtommath/bn_mp_init_set.c \ +libtommath/bn_mp_init_set_int.c libtommath/bn_mp_invmod_slow.c libtommath/bn_mp_prime_rabin_miller_trials.c \ +libtommath/bn_mp_to_signed_bin_n.c libtommath/bn_mp_to_unsigned_bin_n.c \ +libtommath/tommath_class.h libtommath/tommath.h libtommath/tommath_superclass.h +EXTRA_DIST += libtommath/bn_prime_tab.c -libtommath_a_CPPFLAGS = -I$(srcdir)/../extern/libtommath $(AM_CPPFLAGS) +libtommath_a_CPPFLAGS = -I$(srcdir)/libtommath $(AM_CPPFLAGS) noinst_LIBRARIES += libtommath.a libtomcrypt_a_SOURCES = \ -../extern/libtomcrypt/src/ciphers/aes/aes.c \ -../extern/libtomcrypt/src/hashes/md5.c ../extern/libtomcrypt/src/hashes/sha1.c ../extern/libtomcrypt/src/hashes/helper/hash_memory.c \ -../extern/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c ../extern/libtomcrypt/src/math/ltm_desc.c ../extern/libtomcrypt/src/math/multi.c \ -../extern/libtomcrypt/src/math/rand_prime.c ../extern/libtomcrypt/src/misc/base64/base64_decode.c \ -../extern/libtomcrypt/src/misc/base64/base64_encode.c ../extern/libtomcrypt/src/misc/burn_stack.c ../extern/libtomcrypt/src/misc/crypt/crypt.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_argchk.c ../extern/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_find_hash.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c ../extern/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_find_prng.c ../extern/libtomcrypt/src/misc/crypt/crypt_fsa.c ../extern/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c ../extern/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c ../extern/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_register_cipher.c ../extern/libtomcrypt/src/misc/crypt/crypt_register_hash.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_register_prng.c ../extern/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c \ -../extern/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c ../extern/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c \ -../extern/libtomcrypt/src/misc/error_to_string.c ../extern/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c ../extern/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c ../extern/libtomcrypt/src/misc/zeromem.c \ -../extern/libtomcrypt/src/modes/cbc/cbc_decrypt.c ../extern/libtomcrypt/src/modes/cbc/cbc_done.c ../extern/libtomcrypt/src/modes/cbc/cbc_encrypt.c \ -../extern/libtomcrypt/src/modes/cbc/cbc_getiv.c ../extern/libtomcrypt/src/modes/cbc/cbc_setiv.c ../extern/libtomcrypt/src/modes/cbc/cbc_start.c \ -../extern/libtomcrypt/src/modes/cfb/cfb_decrypt.c ../extern/libtomcrypt/src/modes/cfb/cfb_done.c ../extern/libtomcrypt/src/modes/cfb/cfb_encrypt.c \ -../extern/libtomcrypt/src/modes/cfb/cfb_getiv.c ../extern/libtomcrypt/src/modes/cfb/cfb_setiv.c ../extern/libtomcrypt/src/modes/cfb/cfb_start.c \ -../extern/libtomcrypt/src/modes/ctr/ctr_decrypt.c ../extern/libtomcrypt/src/modes/ctr/ctr_done.c ../extern/libtomcrypt/src/modes/ctr/ctr_encrypt.c \ -../extern/libtomcrypt/src/modes/ctr/ctr_getiv.c ../extern/libtomcrypt/src/modes/ctr/ctr_setiv.c ../extern/libtomcrypt/src/modes/ctr/ctr_start.c ../extern/libtomcrypt/src/modes/ctr/ctr_test.c \ -../extern/libtomcrypt/src/modes/ecb/ecb_decrypt.c ../extern/libtomcrypt/src/modes/ecb/ecb_done.c ../extern/libtomcrypt/src/modes/ecb/ecb_encrypt.c \ -../extern/libtomcrypt/src/modes/ecb/ecb_start.c \ -../extern/libtomcrypt/src/modes/ofb/ofb_decrypt.c ../extern/libtomcrypt/src/modes/ofb/ofb_done.c \ -../extern/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c ../extern/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c ../extern/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c \ -../extern/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c ../extern/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c \ -../extern/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c ../extern/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c ../extern/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c \ -../extern/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c ../extern/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c \ -../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c \ -../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c \ -../extern/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c \ -../extern/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c ../extern/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c ../extern/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c \ -../extern/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c ../extern/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c \ -../extern/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c ../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c \ -../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c \ -../extern/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c ../extern/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c \ -../extern/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c ../extern/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c \ -../extern/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c ../extern/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c \ -../extern/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c ../extern/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c \ -../extern/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c ../extern/libtomcrypt/src/pk/dsa/dsa_export.c ../extern/libtomcrypt/src/pk/dsa/dsa_free.c ../extern/libtomcrypt/src/pk/dsa/dsa_import.c \ -../extern/libtomcrypt/src/pk/dsa/dsa_make_key.c ../extern/libtomcrypt/src/pk/dsa/dsa_shared_secret.c ../extern/libtomcrypt/src/pk/dsa/dsa_sign_hash.c \ -../extern/libtomcrypt/src/pk/dsa/dsa_verify_hash.c ../extern/libtomcrypt/src/pk/dsa/dsa_verify_key.c \ -../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c \ -../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c \ -../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c ../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c \ -../extern/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c ../extern/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c ../extern/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c \ -../extern/libtomcrypt/src/pk/rsa/rsa_export.c ../extern/libtomcrypt/src/pk/rsa/rsa_exptmod.c ../extern/libtomcrypt/src/pk/rsa/rsa_free.c ../extern/libtomcrypt/src/pk/rsa/rsa_import.c \ -../extern/libtomcrypt/src/pk/rsa/rsa_make_key.c ../extern/libtomcrypt/src/pk/rsa/rsa_sign_hash.c ../extern/libtomcrypt/src/pk/rsa/rsa_verify_hash.c ../extern/libtomcrypt/src/prngs/fortuna.c \ -../extern/libtomcrypt/src/prngs/rng_get_bytes.c ../extern/libtomcrypt/src/prngs/rng_make_prng.c \ -../extern/libtomcrypt/src/prngs/sprng.c ../extern/libtomcrypt/src/prngs/yarrow.c \ -../extern/libtomcrypt/src/headers/tomcrypt_argchk.h ../extern/libtomcrypt/src/headers/tomcrypt_cfg.h ../extern/libtomcrypt/src/headers/tomcrypt_cipher.h \ -../extern/libtomcrypt/src/headers/tomcrypt_custom.h ../extern/libtomcrypt/src/headers/tomcrypt.h ../extern/libtomcrypt/src/headers/tomcrypt_hash.h \ -../extern/libtomcrypt/src/headers/tomcrypt_mac.h ../extern/libtomcrypt/src/headers/tomcrypt_macros.h ../extern/libtomcrypt/src/headers/tomcrypt_math.h \ -../extern/libtomcrypt/src/headers/tomcrypt_misc.h ../extern/libtomcrypt/src/headers/tomcrypt_pkcs.h ../extern/libtomcrypt/src/headers/tomcrypt_pk.h \ -../extern/libtomcrypt/src/headers/tomcrypt_prng.h -EXTRA_DIST += ../extern/libtomcrypt/src/ciphers/aes/aes_tab.c ../extern/libtomcrypt/src/prngs/sober128tab.c +libtomcrypt/src/ciphers/aes/aes.c \ +libtomcrypt/src/hashes/md5.c libtomcrypt/src/hashes/sha1.c libtomcrypt/src/hashes/helper/hash_memory.c \ +libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c libtomcrypt/src/math/ltm_desc.c libtomcrypt/src/math/multi.c \ +libtomcrypt/src/math/rand_prime.c libtomcrypt/src/misc/base64/base64_decode.c \ +libtomcrypt/src/misc/base64/base64_encode.c libtomcrypt/src/misc/burn_stack.c libtomcrypt/src/misc/crypt/crypt.c \ +libtomcrypt/src/misc/crypt/crypt_argchk.c libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c \ +libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c libtomcrypt/src/misc/crypt/crypt_find_cipher.c \ +libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c \ +libtomcrypt/src/misc/crypt/crypt_find_hash.c libtomcrypt/src/misc/crypt/crypt_find_hash_any.c \ +libtomcrypt/src/misc/crypt/crypt_find_hash_id.c libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c \ +libtomcrypt/src/misc/crypt/crypt_find_prng.c libtomcrypt/src/misc/crypt/crypt_fsa.c libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c \ +libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c \ +libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c \ +libtomcrypt/src/misc/crypt/crypt_register_cipher.c libtomcrypt/src/misc/crypt/crypt_register_hash.c \ +libtomcrypt/src/misc/crypt/crypt_register_prng.c libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c \ +libtomcrypt/src/misc/crypt/crypt_unregister_hash.c libtomcrypt/src/misc/crypt/crypt_unregister_prng.c \ +libtomcrypt/src/misc/error_to_string.c libtomcrypt/src/misc/pkcs5/pkcs_5_1.c libtomcrypt/src/misc/pkcs5/pkcs_5_2.c libtomcrypt/src/misc/zeromem.c \ +libtomcrypt/src/modes/cbc/cbc_decrypt.c libtomcrypt/src/modes/cbc/cbc_done.c libtomcrypt/src/modes/cbc/cbc_encrypt.c \ +libtomcrypt/src/modes/cbc/cbc_getiv.c libtomcrypt/src/modes/cbc/cbc_setiv.c libtomcrypt/src/modes/cbc/cbc_start.c \ +libtomcrypt/src/modes/cfb/cfb_decrypt.c libtomcrypt/src/modes/cfb/cfb_done.c libtomcrypt/src/modes/cfb/cfb_encrypt.c \ +libtomcrypt/src/modes/cfb/cfb_getiv.c libtomcrypt/src/modes/cfb/cfb_setiv.c libtomcrypt/src/modes/cfb/cfb_start.c \ +libtomcrypt/src/modes/ctr/ctr_decrypt.c libtomcrypt/src/modes/ctr/ctr_done.c libtomcrypt/src/modes/ctr/ctr_encrypt.c \ +libtomcrypt/src/modes/ctr/ctr_getiv.c libtomcrypt/src/modes/ctr/ctr_setiv.c libtomcrypt/src/modes/ctr/ctr_start.c libtomcrypt/src/modes/ctr/ctr_test.c \ +libtomcrypt/src/modes/ecb/ecb_decrypt.c libtomcrypt/src/modes/ecb/ecb_done.c libtomcrypt/src/modes/ecb/ecb_encrypt.c \ +libtomcrypt/src/modes/ecb/ecb_start.c \ +libtomcrypt/src/modes/ofb/ofb_decrypt.c libtomcrypt/src/modes/ofb/ofb_done.c \ +libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c \ +libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c \ +libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c \ +libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c \ +libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c \ +libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c \ +libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c \ +libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c \ +libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c \ +libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c \ +libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c \ +libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c \ +libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c \ +libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c \ +libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c \ +libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c libtomcrypt/src/pk/asn1/der/set/der_encode_set.c \ +libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c \ +libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c \ +libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c \ +libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c \ +libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c \ +libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c libtomcrypt/src/pk/dsa/dsa_decrypt_key.c \ +libtomcrypt/src/pk/dsa/dsa_encrypt_key.c libtomcrypt/src/pk/dsa/dsa_export.c libtomcrypt/src/pk/dsa/dsa_free.c libtomcrypt/src/pk/dsa/dsa_import.c \ +libtomcrypt/src/pk/dsa/dsa_make_key.c libtomcrypt/src/pk/dsa/dsa_shared_secret.c libtomcrypt/src/pk/dsa/dsa_sign_hash.c \ +libtomcrypt/src/pk/dsa/dsa_verify_hash.c libtomcrypt/src/pk/dsa/dsa_verify_key.c \ +libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c \ +libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c \ +libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c \ +libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c libtomcrypt/src/pk/rsa/rsa_decrypt_key.c libtomcrypt/src/pk/rsa/rsa_encrypt_key.c \ +libtomcrypt/src/pk/rsa/rsa_export.c libtomcrypt/src/pk/rsa/rsa_exptmod.c libtomcrypt/src/pk/rsa/rsa_free.c libtomcrypt/src/pk/rsa/rsa_import.c \ +libtomcrypt/src/pk/rsa/rsa_make_key.c libtomcrypt/src/pk/rsa/rsa_sign_hash.c libtomcrypt/src/pk/rsa/rsa_verify_hash.c libtomcrypt/src/prngs/fortuna.c \ +libtomcrypt/src/prngs/rng_get_bytes.c libtomcrypt/src/prngs/rng_make_prng.c \ +libtomcrypt/src/prngs/sprng.c libtomcrypt/src/prngs/yarrow.c \ +libtomcrypt/src/headers/tomcrypt_argchk.h libtomcrypt/src/headers/tomcrypt_cfg.h libtomcrypt/src/headers/tomcrypt_cipher.h \ +libtomcrypt/src/headers/tomcrypt_custom.h libtomcrypt/src/headers/tomcrypt.h libtomcrypt/src/headers/tomcrypt_hash.h \ +libtomcrypt/src/headers/tomcrypt_mac.h libtomcrypt/src/headers/tomcrypt_macros.h libtomcrypt/src/headers/tomcrypt_math.h \ +libtomcrypt/src/headers/tomcrypt_misc.h libtomcrypt/src/headers/tomcrypt_pkcs.h libtomcrypt/src/headers/tomcrypt_pk.h \ +libtomcrypt/src/headers/tomcrypt_prng.h +EXTRA_DIST += libtomcrypt/src/ciphers/aes/aes_tab.c libtomcrypt/src/prngs/sober128tab.c -libtomcrypt_a_CPPFLAGS = -I$(srcdir)/../extern/libtomcrypt/src/headers $(AM_CPPFLAGS) +libtomcrypt_a_CPPFLAGS = -I$(srcdir)/libtomcrypt/src/headers $(AM_CPPFLAGS) noinst_LIBRARIES += libtomcrypt.a From 799bbc0a5c3723bd9ac2cbee042a438eee73bb32 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 19:18:03 -0400 Subject: [PATCH 006/333] Make this use ScreenTextEntry. The rest will be fixed once I find out why I'm having compilation issues. --- Themes/_fallback/Languages/en.ini | 1 + src/ScreenEdit.cpp | 26 ++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 0847beabb8..51db471be3 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1232,6 +1232,7 @@ Enter a new genre.=Enter a new genre. Enter a new credit.=Enter a new credit. Enter a new description.=Enter a new description. Enter a new chart style.=Enter a new chart style (e.g. "Pad", "Keyboard"). +Enter a new meter.=Enter the difficulty rating for this chart. Enter the author who made this step pattern.=Enter the author who made this step pattern. Enter the offset for the song.=Enter the beat 0 offset for the song. Enter a new last beat hint.=Enter a new last beat hint. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 52e9c62ea0..8f02b58eb9 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -73,6 +73,7 @@ AutoScreenMessage( SM_BackFromCourseModeMenu ); AutoScreenMessage( SM_DoRevertToLastSave ); AutoScreenMessage( SM_DoRevertFromDisk ); AutoScreenMessage( SM_BackFromTimingDataInformation ); +AutoScreenMessage( SM_BackFromDifficultyMeterChange ); AutoScreenMessage( SM_BackFromBPMChange ); AutoScreenMessage( SM_BackFromStopChange ); AutoScreenMessage( SM_BackFromDelayChange ); @@ -519,7 +520,7 @@ static MenuDef g_AreaMenu( static MenuDef g_StepsInformation( "ScreenMiniMenuStepsInformation", MenuRowDef( ScreenEdit::difficulty, "Difficulty", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::meter, "Meter", true, EditMode_Practice, true, false, 0, MIN_METER, MAX_METER ), + MenuRowDef( ScreenEdit::meter, "Meter", true, EditMode_Practice, true, false, 0, NULL ), MenuRowDef( ScreenEdit::description, "Description", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::chartstyle, "Chart Style", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::step_credit, "Step Author", true, EditMode_Practice, true, true, 0, NULL ), @@ -2614,6 +2615,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { HandleTimingDataInformationChoice( (TimingDataInformationChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers ); } + else if( SM == SM_BackFromDifficultyMeterChange ) + { + int i; + std::istringstream ss( ScreenTextEntry::s_sLastAnswer ); + ss >> i; + GAMESTATE->m_pCurSteps[PLAYER_1]->SetMeter(i); + SetDirty( true ); + } else if( SM == SM_BackFromBPMChange ) { float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); @@ -3126,7 +3135,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns } g_StepsInformation.rows[difficulty].iDefaultChoice = pSteps->GetDifficulty(); g_StepsInformation.rows[difficulty].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full); - g_StepsInformation.rows[meter].iDefaultChoice = clamp( pSteps->GetMeter()-1, 0, MAX_METER+1 ); + g_StepsInformation.rows[meter].SetOneUnthemedChoice( ssprintf("%d", pSteps->GetMeter()-1) ); g_StepsInformation.rows[meter].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Home); g_StepsInformation.rows[predict_meter].SetOneUnthemedChoice( ssprintf("%.2f",pSteps->PredictMeter()) ); g_StepsInformation.rows[description].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full); @@ -3590,13 +3599,12 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns static LocalizedString ENTER_NEW_DESCRIPTION( "ScreenEdit", "Enter a new description." ); static LocalizedString ENTER_NEW_CHART_STYLE( "ScreenEdit", "Enter a new chart style." ); static LocalizedString ENTER_NEW_STEP_AUTHOR( "ScreenEdit", "Enter the author who made this step pattern." ); +static LocalizedString ENTER_NEW_METER( "ScreenEdit", "Enter a new meter." ); void ScreenEdit::HandleStepsInformationChoice( StepsInformationChoice c, const vector &iAnswers ) { Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1]; Difficulty dc = (Difficulty)iAnswers[difficulty]; pSteps->SetDifficulty( dc ); - int iMeter = iAnswers[meter]+1; - pSteps->SetMeter( iMeter ); switch( c ) { @@ -3633,6 +3641,16 @@ void ScreenEdit::HandleStepsInformationChoice( StepsInformationChoice c, const v NULL ); break; + case meter: + ScreenTextEntry::TextEntry( + SM_BackFromDifficultyMeterChange, + ENTER_NEW_METER, + ssprintf("%d", m_pSteps->GetMeter()), + 4 + ); + break; + default: + break; } } From b6eb2f0106e678f4a57d141bc5f30fb6104bf3c9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 19:24:44 -0400 Subject: [PATCH 007/333] Minor fix. --- Xcode/stepmania.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 7f4bc6c9ad..160aae89cc 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -7173,7 +7173,7 @@ SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_INSTALLED_PRODUCT = NO; STRIP_STYLE = "non-global"; - USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../src/jsoncpp/include"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include"; }; name = Debug; }; @@ -7709,7 +7709,7 @@ SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_INSTALLED_PRODUCT = YES; STRIP_STYLE = "non-global"; - USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../src/jsoncpp/include"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include"; }; name = PerformanceDebug; }; @@ -8044,7 +8044,7 @@ SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_INSTALLED_PRODUCT = YES; STRIP_STYLE = "non-global"; - USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../src/jsoncpp/include"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include"; }; name = Native; }; @@ -8174,7 +8174,7 @@ SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_INSTALLED_PRODUCT = YES; STRIP_STYLE = "non-global"; - USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../src/jsoncpp/include"; + USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include"; }; name = Universal; }; From cba408f92b5e0fb41aacf47934c4db52891175e1 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 19:28:23 -0400 Subject: [PATCH 008/333] Include excludes for consistency. --- Xcode/stepmania.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 160aae89cc..b0540e5505 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -7123,6 +7123,7 @@ COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.framework *.gch *.xcode* (*) CVS .svn .hg .git"; GCC_ALTIVEC_EXTENSIONS = YES; GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = YES; @@ -7660,6 +7661,7 @@ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.framework *.gch *.xcode* (*) CVS .svn .hg .git"; GCC_ALTIVEC_EXTENSIONS = YES; GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = YES; @@ -7995,6 +7997,7 @@ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.framework *.gch *.xcode* (*) CVS .svn .hg .git"; GCC_ALTIVEC_EXTENSIONS = YES; GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = YES; @@ -8124,6 +8127,7 @@ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.framework *.gch *.xcode* (*) CVS .svn .hg .git"; GCC_ALTIVEC_EXTENSIONS = YES; GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = YES; From a6500a0dc14cff75b346111d7fde4fc70f841bf9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 19:34:53 -0400 Subject: [PATCH 009/333] Don't clamp meter on write. Here's yet another cache refresh for the trouble. --- src/NotesWriterSM.cpp | 2 +- src/NotesWriterSSC.cpp | 2 +- src/Song.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index 95d14e75fb..c50c9890f5 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -274,7 +274,7 @@ static RString GetSMNotesTag( const Song &song, const Steps &in ) RString desc = (USE_CREDIT ? in.GetCredit() : in.GetDescription()); lines.push_back( ssprintf( " %s:", SmEscape(desc).c_str() ) ); lines.push_back( ssprintf( " %s:", DifficultyToString(in.GetDifficulty()).c_str() ) ); - lines.push_back( ssprintf( " %d:", clamp( in.GetMeter(), MIN_METER, MAX_METER ) ) ); + lines.push_back( ssprintf( " %d:", in.GetMeter() ) ); vector asRadarValues; // SM files don't use fakes for radar data. Keep it that way. diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 921d082bde..69ca696756 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -294,7 +294,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa lines.push_back( ssprintf( "#DESCRIPTION:%s;", SmEscape(in.GetDescription()).c_str() ) ); lines.push_back( ssprintf( "#CHARTSTYLE:%s;", SmEscape(in.GetChartStyle()).c_str() ) ); lines.push_back( ssprintf( "#DIFFICULTY:%s;", DifficultyToString(in.GetDifficulty()).c_str() ) ); - lines.push_back( ssprintf( "#METER:%d;", clamp( in.GetMeter(), MIN_METER, MAX_METER ) ) ); + lines.push_back( ssprintf( "#METER:%d;", in.GetMeter() ) ); vector asRadarValues; FOREACH_PlayerNumber( pn ) diff --git a/src/Song.cpp b/src/Song.cpp index 23f68f2891..5743eb9199 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 170; +const int FILE_CACHE_VERSION = 171; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; From 0601a5ce3b5db5af067daf3074eab18bf0110d63 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 7 May 2011 22:42:30 -0400 Subject: [PATCH 010/333] Funny how I can add metrics but not modify them. --- Themes/_fallback/metrics.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 31538e98b5..13b0757ec4 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -2070,7 +2070,7 @@ ExplanationP2OffCommand= ExplanationTogetherX=SCREEN_CENTER_X ExplanationTogetherY=SCREEN_CENTER_Y+184 ExplanationTogetherOnCommand=shadowlength,0;zoom,0.75;wrapwidthpixels,(SCREEN_WIDTH*0.9375)*1.25;cropright,1;linear,0.5;cropright,0 -ExplanationTogetherOffCommand= +ExplanationTogetherOffCommand=stoptweening DisqualifyP1X= DisqualifyP1Y= DisqualifyP1OnCommand=visible,false @@ -2471,7 +2471,7 @@ SeparateExitRowY=SCREEN_CENTER_Y+180 ExplanationTogetherX=SCREEN_CENTER_X ExplanationTogetherY=SCREEN_CENTER_Y+174 ExplanationTogetherOnCommand=zoom,0.75;shadowlength,0;wrapwidthpixels,600/0.75;cropright,1;linear,0.5;cropright,0 -ExplanationTogetherOffCommand= +ExplanationTogetherOffCommand=stoptweening [ScreenOptionsSimpleService] Fallback="ScreenOptionsSimple" @@ -2552,7 +2552,7 @@ LineHighlightP2ChangeToExitCommand= ExplanationTogetherX=SCREEN_CENTER_X ExplanationTogetherY=SCREEN_CENTER_Y+174 ExplanationTogetherOnCommand=zoom,0.625;shadowlength,0;wrapwidthpixels,600/0.665;cropright,1;linear,0.5;cropright,0 -ExplanationTogetherOffCommand= +ExplanationTogetherOffCommand=stoptweening [ScreenOptionsServiceExtendedChild] Fallback="ScreenOptionsServiceChild" From e324d8f469bada63882bdfa09fda4a21ee5aa9ce Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 8 May 2011 12:11:07 -0500 Subject: [PATCH 011/333] typo --- Docs/WindowsNotes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/WindowsNotes.txt b/Docs/WindowsNotes.txt index e51d6fb629..4cc2d13f9f 100644 --- a/Docs/WindowsNotes.txt +++ b/Docs/WindowsNotes.txt @@ -4,7 +4,7 @@ If you are using Windows Vista or Windows 7, please do not install StepMania SSC [Using Google Chrome?] If you are using Google Chrome as your primary web browser, you will have to perform some extra steps to get stepmania:// URI handling to work: -Find yout user data +Find your user data Windows XP: C:\Documents and Settings\\Local Settings\Application Data\Google\Chrome\User Data Windows Vista/7: C:\Users\\AppData\Local\Google\Chrome\User Data From dd03c176b1585ffeca1ce17a21d6c1308af188a7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 8 May 2011 17:00:06 -0400 Subject: [PATCH 012/333] Start unifying png versions. 1.5.2 in this case. --- extern/libpng/include/1.2.7/png.h | 3361 ------------- extern/libpng/include/1.2.7/pngconf.h | 1376 ----- extern/libpng/include/png.c | 2362 +++++++++ extern/libpng/include/png.h | 2259 ++++----- extern/libpng/include/pngconf.h | 1751 ++----- extern/libpng/include/pngdebug.h | 157 + extern/libpng/include/pngerror.c | 447 ++ extern/libpng/include/pngget.c | 1032 ++++ extern/libpng/include/pnginfo.h | 270 + extern/libpng/include/pngmem.c | 658 +++ extern/libpng/include/pngpread.c | 1854 +++++++ extern/libpng/include/pngpriv.h | 1246 +++++ extern/libpng/include/pngread.c | 1473 ++++++ extern/libpng/include/pngrio.c | 176 + extern/libpng/include/pngrtran.c | 4303 ++++++++++++++++ extern/libpng/include/pngrutil.c | 3632 +++++++++++++ extern/libpng/include/pngset.c | 1225 +++++ extern/libpng/include/pngstruct.h | 308 ++ extern/libpng/include/pngtest.c | 1787 +++++++ extern/libpng/include/pngtrans.c | 674 +++ extern/libpng/include/pngvalid.c | 6709 +++++++++++++++++++++++++ extern/libpng/include/pngwio.c | 254 + extern/libpng/include/pngwrite.c | 1605 ++++++ extern/libpng/include/pngwtran.c | 631 +++ extern/libpng/include/pngwutil.c | 2948 +++++++++++ 25 files changed, 35137 insertions(+), 7361 deletions(-) delete mode 100644 extern/libpng/include/1.2.7/png.h delete mode 100644 extern/libpng/include/1.2.7/pngconf.h create mode 100644 extern/libpng/include/png.c create mode 100644 extern/libpng/include/pngdebug.h create mode 100644 extern/libpng/include/pngerror.c create mode 100644 extern/libpng/include/pngget.c create mode 100644 extern/libpng/include/pnginfo.h create mode 100644 extern/libpng/include/pngmem.c create mode 100644 extern/libpng/include/pngpread.c create mode 100644 extern/libpng/include/pngpriv.h create mode 100644 extern/libpng/include/pngread.c create mode 100644 extern/libpng/include/pngrio.c create mode 100644 extern/libpng/include/pngrtran.c create mode 100644 extern/libpng/include/pngrutil.c create mode 100644 extern/libpng/include/pngset.c create mode 100644 extern/libpng/include/pngstruct.h create mode 100644 extern/libpng/include/pngtest.c create mode 100644 extern/libpng/include/pngtrans.c create mode 100644 extern/libpng/include/pngvalid.c create mode 100644 extern/libpng/include/pngwio.c create mode 100644 extern/libpng/include/pngwrite.c create mode 100644 extern/libpng/include/pngwtran.c create mode 100644 extern/libpng/include/pngwutil.c diff --git a/extern/libpng/include/1.2.7/png.h b/extern/libpng/include/1.2.7/png.h deleted file mode 100644 index 2ac19465d4..0000000000 --- a/extern/libpng/include/1.2.7/png.h +++ /dev/null @@ -1,3361 +0,0 @@ -/* png.h - header file for PNG reference library - * - * libpng version 1.2.7 - September 12, 2004 - * Copyright (c) 1998-2004 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.) - * - * 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.2.7 - September 12, 2004: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_uint_32 rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* 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 - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ -typedef struct png_struct_def png_struct; -typedef png_struct FAR * png_structp; - -typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) -typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); -#endif -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE 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 - -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf; /* used in png_error */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ - png_error_ptr warning_fn; /* function for printing warnings */ - 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 */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr write_user_transform_fn; /* user write transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - png_size_t zbuf_size; /* size of zbuf */ - 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 */ - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_uint_32 rowbytes; /* size of row in bytes */ - png_uint_32 irowbytes; /* size of current interlaced row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row */ - png_bytep row_buf; /* buffer to save current (unfiltered) row */ - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - 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_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte chunk_name[5]; /* null-terminated name of current chunk */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -#ifdef PNG_LEGACY_SUPPORTED - png_byte filler; /* filler byte for pixel expansion */ -#else - png_uint_16 filler; /* filler bytes for pixel expansion */ -#endif -#endif - -#if defined(PNG_bKGD_SUPPORTED) - png_byte background_gamma_type; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma; -# endif - png_color_16 background; /* background color in screen gamma space */ -#if defined(PNG_READ_GAMMA_SUPPORTED) - png_color_16 background_1; /* background normalized to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_flush_ptr output_flush_fn;/* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma; /* file gamma value */ - float screen_gamma; /* screen gamma value (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans; /* transparency values for paletted files */ - png_color_16 trans_values; /* transparency values for non-paletted files */ -#endif - - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ - -# if defined(PNG_TEXT_SUPPORTED) - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* for the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - png_bytep palette_lookup; /* lookup table for dithering */ - png_bytep dither_index; /* index translation for palette files */ -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ -#endif - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_charp time_buffer; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - -#ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) - png_voidp user_chunk_ptr; - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - int num_chunk_list; - png_bytep chunk_list; -#endif - -/* New members added in libpng-1.0.3 */ -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_byte rgb_to_gray_status; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - png_uint_16 rgb_to_gray_blue_coeff; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* changed from png_byte to png_uint_32 at version 1.2.0 */ -#ifdef PNG_1_0_X - png_byte mng_features_permitted; -#else - png_uint_32 mng_features_permitted; -#endif /* PNG_1_0_X */ -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_byte filter_type; -#endif - -#if defined(PNG_1_0_X) || (defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)) -/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ - png_uint_32 row_buf_size; -#endif - -/* New members added in libpng-1.2.0 */ -#if !defined(PNG_1_0_X) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) - png_byte mmx_bitdepth_threshold; - png_uint_32 mmx_rowbytes_threshold; - png_uint_32 asm_flags; -#endif - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is */ - /* in the palette */ - png_bytep palette_to_index; /* which original index points to this */ - /* palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; -#endif - -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_2_7; - -typedef png_struct FAR * FAR * png_structpp; - -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ -extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -extern PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -extern PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_uint_32 size)); -#endif - -/* Reset the compression stream */ -extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((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)); -extern PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((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)); -#endif - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -extern PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)); - -/* Initialize the info structure (old interface - DEPRECATED) */ -extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); -#undef png_info_init -#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ - png_sizeof(png_info)); -extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the information before the actual image data. */ -extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); -#endif - -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ -#if defined(PNG_WRITE_tIME_SUPPORTED) -/* convert from a struct tm to png_time */ -extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); - -/* convert from time_t to png_time. Uses gmtime() */ -extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_WRITE_tIME_SUPPORTED */ -#endif /* _WIN32_WCE */ - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* Expand the grayscale to 24-bit RGB if necessary. */ -extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); -#endif - -extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_filler) PNGARG((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. */ -#if !defined(PNG_1_0_X) -extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -#endif -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Handle alpha and tRNS by replacing with a background color. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -#endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip the second byte of information from a 16-bit depth file. */ -extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* Turn on dithering, and reduce the palette to the number of colors available. */ -extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_dither)); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif - -#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ -/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ -extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, - int empty_plte_permitted)); -#endif - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set how many lines between output flushes - 0 for no flushing */ -extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); -#endif - -/* optional update palette with requested transformations */ -extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); - -/* optional call to update the users info structure */ -extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read one or more rows of image data. */ -extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read a row of data. */ -extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the whole image into memory at once. */ -extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); -#endif - -/* write a row of image data */ -extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); - -/* write a few rows of image data */ -extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); - -/* write the image data */ -extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); - -/* writes the end of the PNG file. */ -extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the end of the PNG file. */ -extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* free any memory associated with the png_info_struct */ -extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* free all memory used by the read (old method - NOT DLL EXPORTED) */ -extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, - png_infop end_info_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); - -/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ -extern void png_write_destroy PNGARG((png_structp png_ptr)); - -/* set the libpng method of handling chunk CRC errors */ -extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() to 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, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* 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, - * these values may not correspond directly to the zlib compression levels. - */ -extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); - -extern PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); - -extern PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); - -extern PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); - -extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * 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 - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - -#if !defined(PNG_NO_STDIO) -/* Initialize the input/output for the PNG file to the default functions. */ -extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -extern PNG_EXPORT(void,png_set_error_fn) PNGARG((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 */ -extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - */ -extern PNG_EXPORT(void,png_set_write_fn) PNGARG((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. */ -extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((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). */ -extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((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 */ -extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((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 */ -extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp - png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((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 */ -extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); - -/* function to be called when data becomes available */ -extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ -extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_uint_32 size)); - -#if defined(PNG_1_0_X) -# define png_malloc_warn png_malloc -#else -/* Added at libpng version 1.2.4 */ -extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_uint_32 size)); -#endif - -/* frees a pointer allocated by png_malloc() */ -extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); - -#if defined(PNG_1_0_X) -/* Function to allocate memory for zlib. */ -extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, - uInt size)); - -/* Function to free memory for zlib */ -extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); -#endif - -/* Free data that was allocated internally */ -extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); -#ifdef PNG_FREE_ME_SUPPORTED -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); -#endif -/* assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_uint_32 size)); -extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); -#endif - -extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, - png_voidp s1, png_voidp s2, png_uint_32 size)); - -extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, - png_voidp s1, int value, png_uint_32 size)); - -#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ -extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ - -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); - -/* The same, but the chunk name is prepended to the error string. */ -extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); - -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* Returns row_pointers, which is an array of pointers to scanlines that was -returned from png_read_png(). */ -extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use -by png_write_png(). */ -extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image height in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image bit_depth. */ -extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image color_type. */ -extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image filter_type. */ -extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image interlace_type. */ -extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image compression_type. */ -extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); -#endif - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((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)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((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 -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM) PNGARG((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)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((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 -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((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)); - -extern PNG_EXPORT(void,png_set_IHDR) PNGARG((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)); - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); - -extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp palette, int num_palette)); - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); -#endif - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) -/* png_get_text also returns the number of text chunks in *num_text */ -extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* - * 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 - * they will never be NULL pointers. - */ - -#if defined(PNG_TEXT_SUPPORTED) -extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans, int *num_trans, - png_color_16p *trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans, int num_trans, - png_color_16p trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -#endif - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED */ - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behavour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); -#endif -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); -#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, - you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ -extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* The "params" pointer is currently not used and is for future expansion. */ -extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -#endif - -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - */ -#ifdef PNG_DEBUG -#if (PNG_DEBUG > 0) -#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -#include -#if (PNG_DEBUG > 1) -#define png_debug(l,m) _RPT0(_CRT_WARN,m) -#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) -#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) -#endif -#else /* PNG_DEBUG_FILE || !_MSC_VER */ -#ifndef PNG_DEBUG_FILE -#define PNG_DEBUG_FILE stderr -#endif /* PNG_DEBUG_FILE */ -#if (PNG_DEBUG > 1) -#define png_debug(l,m) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ -} -#define png_debug1(l,m,p1) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ -} -#define png_debug2(l,m,p1,p2) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ -} -#endif /* (PNG_DEBUG > 1) */ -#endif /* _MSC_VER */ -#endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ -#ifndef png_debug -#define png_debug(l, m) -#endif -#ifndef png_debug1 -#define png_debug1(l, m, p1) -#endif -#ifndef png_debug2 -#define png_debug2(l, m, p1, p2) -#endif - -extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void)); - -extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Added to version 1.2.0 */ -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 -#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 -#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 -#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 -#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 -#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 -#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ - -#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) -#define PNG_MMX_WRITE_FLAGS ( 0 ) - -#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ - | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ - | PNG_MMX_READ_FLAGS \ - | PNG_MMX_WRITE_FLAGS ) - -#define PNG_SELECT_READ 1 -#define PNG_SELECT_WRITE 2 - -#if !defined(PNG_1_0_X) -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) - PNGARG((int flag_select, int *compilerID)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) - PNGARG((int flag_select)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flags) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) - PNGARG((png_structp png_ptr)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_asm_flags) - PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_mmx_thresholds) - PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold)); - -#endif /* PNG_1_0_X */ -#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ - -#if !defined(PNG_1_0_X) -/* png.c, pnggccrd.c, or pngvcrd.c */ -extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); -#endif - -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp - png_ptr)); -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 - \ - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L - \ - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) - -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -/* These next functions are used internally in the code. They generally - * shouldn't be used unless you are writing code to add or replace some - * functionality in libpng. More information about most functions can - * be found in the files where the functions are located. - */ - -#if defined(PNG_INTERNAL) - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 -#define PNG_HAVE_IEND 0x10 -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 -#define PNG_HAVE_sRGB 0x80 -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 - -/* flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_DITHER 0x0040 -#define PNG_BACKGROUND 0x0080 -#define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000L -#define PNG_PACKSWAP 0x10000L -#define PNG_SWAP_ALPHA 0x20000L -#define PNG_STRIP_ALPHA 0x40000L -#define PNG_INVERT_ALPHA 0x80000L -#define PNG_USER_TRANSFORM 0x100000L -#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 */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ - -/* flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 - -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_SHIFT 8 -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_SHIFT 3 -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - -/* flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 -#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 -#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 -#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 -#define PNG_FLAG_ZLIB_FINISHED 0x0020 -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_FREE_PLTE 0x1000 -#define PNG_FLAG_FREE_TRNS 0x2000 -#define PNG_FLAG_FREE_HIST 0x4000 -#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_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) - -#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) - -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* save typing and make code easier to understand */ - -#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ - abs((int)((c1).green) - (int)((c2).green)) + \ - abs((int)((c1).blue) - (int)((c2).blue))) - -/* Added to libpng-1.2.6 JB */ -#define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ - (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) - -/* PNG_OUT_OF_RANGE returns true if value is outside the range - ideal-delta..ideal+delta. Each argument is evaluated twice. - "ideal" and "delta" should be constants, normally simple - integers, "value" a variable. Added to libpng-1.2.6 JB */ -#define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) - -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ -#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* place to hold the signature string for a PNG file. */ -#ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8]; -#else -#define png_sig png_sig_bytes(NULL) -#endif -#endif /* PNG_NO_EXTERN */ - -/* Constant strings for known chunk types. If you need to add a chunk, - * define the name here, and add an invocation of the macro in png.c and - * wherever it's needed. - */ -#define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} -#define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} -#define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} -#define PNG_PLTE const png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} -#define PNG_bKGD const png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} -#define PNG_cHRM const png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} -#define PNG_gAMA const png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} -#define PNG_hIST const png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} -#define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} -#define PNG_iTXt const png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} -#define PNG_oFFs const png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} -#define PNG_pCAL const png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} -#define PNG_sCAL const png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} -#define PNG_pHYs const png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} -#define PNG_sBIT const png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} -#define PNG_sPLT const png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} -#define PNG_sRGB const png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} -#define PNG_tEXt const png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} -#define PNG_tIME const png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} -#define PNG_tRNS const png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} -#define PNG_zTXt const png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} - -#ifdef PNG_USE_GLOBAL_ARRAYS -PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5]; -PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5]; -#endif /* PNG_USE_GLOBAL_ARRAYS */ - - -/* Inline macros to do direct reads of bytes from the input buffer. These - * require that you are using an architecture that uses PNG byte ordering - * (MSB first) and supports unaligned data storage. I think that PowerPC - * in big-endian mode and 680x0 are the only ones that will support this. - * The x86 line of processors definitely do not. The png_get_int_32() - * routine also assumes we are using two's complement format for negative - * values, which is almost certainly true. - */ -#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) -# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) -# define png_get_int_32(buf) ( *((png_int_32p) (buf))) -# endif -# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) -# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) -#else -# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) -PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf)); -# endif -PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf)); -PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf)); -#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ -PNG_EXTERN png_uint_32 png_get_uint_31 PNGARG((png_structp png_ptr, - png_bytep buf)); - -/* Initialize png_ptr struct for reading, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_read_struct instead). - */ -extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); -#undef png_read_init -#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); - -/* Initialize png_ptr struct for writing, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_write_struct instead). - */ -extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); -#undef png_write_init -#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); - -/* Allocate memory for an internal libpng struct */ -PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); - -/* Free memory from internal libpng struct */ -PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - -PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr - malloc_fn, png_voidp mem_ptr)); -PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, - png_free_ptr free_fn, png_voidp mem_ptr)); - -/* Free any memory that info_ptr points to and reset struct. */ -PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_1_0_X -/* Function to allocate memory for zlib. */ -PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); - -/* Function to free memory for zlib */ -PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); - -#ifdef PNG_SIZE_T -/* Function to convert a sizeof an item to png_sizeof item */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); -#endif - -/* Next four functions are used internally as callbacks. PNGAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - -PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif - -PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -#if !defined(PNG_NO_STDIO) -PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); -#endif -#endif -#else /* PNG_1_0_X */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif -#endif /* PNG_1_0_X */ - -/* Reset the CRC variable */ -PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); - -/* Write the "data" buffer to whatever output you are using. */ -PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read data from whatever input you are using into the "data" buffer */ -PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read bytes into buf, and update png_ptr->crc */ -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) -PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, - int comp_type, png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_length, png_size_t *data_length)); -#endif - -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); - -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ -PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, - png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); -#endif - - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). - * The only currently known PNG chunks that use signed numbers are - * the ancillary extension chunks, oFFs and pCAL. - */ -PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i)); - -#if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED) -PNG_EXTERN void png_save_int_32 PNGARG((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, - * just to avoid potential problems on pre-ANSI C compilers. - */ -PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i)); - -/* simple function to write the signature */ -PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); - -/* write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ -PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, - png_uint_32 height, - int bit_depth, int color_type, int compression_method, int filter_method, - int interlace_method)); - -PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, - png_uint_32 num_pal)); - -PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); - -#if defined(PNG_WRITE_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point - file_gamma)); -#endif -#endif - -#if defined(PNG_WRITE_sBIT_SUPPORTED) -PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, - int color_type)); -#endif - -#if defined(PNG_WRITE_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_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)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_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 - -#if defined(PNG_WRITE_sRGB_SUPPORTED) -PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, - int intent)); -#endif - -#if defined(PNG_WRITE_iCCP_SUPPORTED) -PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_charp name, int compression_type, - png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, - png_sPLT_tp palette)); -#endif - -#if defined(PNG_WRITE_tRNS_SUPPORTED) -PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, - png_color_16p values, int number, int color_type)); -#endif - -#if defined(PNG_WRITE_bKGD_SUPPORTED) -PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_color_16p values, int color_type)); -#endif - -#if defined(PNG_WRITE_hIST_SUPPORTED) -PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, - int num_hist)); -#endif - -#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, - png_charp key, png_charpp new_key)); -#endif - -#if defined(PNG_WRITE_tEXt_SUPPORTED) -PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len)); -#endif - -#if defined(PNG_WRITE_zTXt_SUPPORTED) -PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len, int compression)); -#endif - -#if defined(PNG_WRITE_iTXt_SUPPORTED) -PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_charp key, png_charp lang, png_charp lang_key, - png_charp text)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ -PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_WRITE_oFFs_SUPPORTED) -PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type)); -#endif - -#if defined(PNG_WRITE_pCAL_SUPPORTED) -PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, - png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params)); -#endif - -#if defined(PNG_WRITE_pHYs_SUPPORTED) -PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, - png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type)); -#endif - -#if defined(PNG_WRITE_tIME_SUPPORTED) -PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_timep mod_time)); -#endif - -#if defined(PNG_WRITE_sCAL_SUPPORTED) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) -PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, - int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_charp width, png_charp height)); -#endif -#endif -#endif - -/* Called when finished processing a row of data */ -PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); - -/* Internal use only. Called before first row of data */ -PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); -#endif - -/* combine a row of data, dealing with alpha, etc. if requested */ -PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int mask)); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) -/* expand an interlaced row */ -/* OLD pre-1.0.9 interface: -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); - */ -PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); -#endif - -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* grab pixels out of a row for an interlaced pass */ -PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass)); -#endif - -/* unfilter a row */ -PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, - png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); - -/* Choose the best filter to use and filter the row data */ -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)); -/* optional call to update the users info structure */ -PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -/* these are the functions that do the transformations */ -#if defined(PNG_READ_FILLER_SUPPORTED) -PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 filler, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#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)); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop - row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) -PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p sig_bits)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, - png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); - -# if defined(PNG_CORRECT_PALETTE_SUPPORTED) -PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette)); -# endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) -PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth)); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p bit_depth)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background, - png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_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_color_16p trans_values, png_color_16p background)); -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift)); -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); -PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, - png_bytep row, png_color_16p trans_value)); -#endif - -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* decode the IHDR chunk */ -PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); - -#if defined(PNG_READ_bKGD_SUPPORTED) -PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_cHRM_SUPPORTED) -PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_gAMA_SUPPORTED) -PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_hIST_SUPPORTED) -PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_iCCP_SUPPORTED) -extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_oFFs_SUPPORTED) -PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pCAL_SUPPORTED) -PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pHYs_SUPPORTED) -PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sBIT_SUPPORTED) -PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) -PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sPLT_SUPPORTED) -extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#if defined(PNG_READ_sRGB_SUPPORTED) -PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tIME_SUPPORTED) -PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tRNS_SUPPORTED) -PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); - -PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_bytep chunk_name)); - -/* handle the transformations for reading and writing */ -PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); - -PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); -PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); -PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -/* png.c */ /* PRIVATE */ -PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); -#endif -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -#endif /* PNG_INTERNAL */ - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* do not put anything past this line */ -#endif /* PNG_H */ diff --git a/extern/libpng/include/1.2.7/pngconf.h b/extern/libpng/include/1.2.7/pngconf.h deleted file mode 100644 index b0aedb4825..0000000000 --- a/extern/libpng/include/1.2.7/pngconf.h +++ /dev/null @@ -1,1376 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.2.7 - September 12, 2004 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 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.) - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifdef PNG_USER_CONFIG -#include "pngusr.h" -#endif - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. - */ -#if defined(__CYGWIN__) -# if defined(ALL_STATIC) -# if defined(PNG_BUILD_DLL) -# undef PNG_BUILD_DLL -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# if !defined(PNG_STATIC) -# define PNG_STATIC -# endif -# else -# if defined (PNG_BUILD_DLL) -# if defined(PNG_STATIC) -# undef PNG_STATIC -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# else -# if defined(PNG_STATIC) -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# else -# if !defined(PNG_USE_DLL) -# define PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# endif -# endif -# endif -#endif - -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - -#if defined(_WIN32_WCE) -# include - /* Console I/O functions are not supported on WindowsCE */ -# define PNG_NO_CONSOLE_IO -# ifdef PNG_DEBUG -# undef PNG_DEBUG -# endif -#endif - -#ifdef PNG_BUILD_DLL -# ifndef PNG_CONSOLE_IO_SUPPORTED -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else -# if !defined(_WIN32_WCE) -/* "stdio.h" functions are not supported on WindowsCE */ -# include -# endif -# endif - -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else - -#ifdef _NO_PROTO -# define PNGARG(arglist) () -# ifndef PNG_TYPECAST_NULL -# define PNG_TYPECAST_NULL -# endif -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ - -#endif /* OF */ - -#endif /* PNGARG */ - -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS -# endif -#endif - -/* enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) -# include -#endif - -#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - */ - -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __png.h__ already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ - - /* include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE -# endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ - -#ifdef BSD -# include -#else -# include -#endif - -/* Other defines for things like memory and the like can go here. */ -#ifdef PNG_INTERNAL - -#include - -/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which - * aren't usually used outside the library (as far as I know), so it is - * debatable if they should be exported at all. In the future, when it is - * possible to have run-time registry of chunk-handling functions, some of - * these will be made available again. -#define PNG_EXTERN extern - */ -#define PNG_EXTERN - -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) -# if defined(MACOS) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* Codewarrior on NT has linking problems without this. */ -#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) -# define PNG_ALWAYS_EXTERN -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -/* I have no idea why is this necessary... */ -#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ - defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) -# include -#endif - -/* This controls how fine the dithering gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with dithering quality can decrease some or all of these. - */ -#ifndef PNG_DITHER_RED_BITS -# define PNG_DITHER_RED_BITS 5 -#endif -#ifndef PNG_DITHER_GREEN_BITS -# define PNG_DITHER_GREEN_BITS 5 -#endif -#ifndef PNG_DITHER_BLUE_BITS -# define PNG_DITHER_BLUE_BITS 5 -#endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 -#endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 -#endif - -#endif /* PNG_INTERNAL */ - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - */ - -#ifndef PNG_NO_CONST -# define PNG_CONST const -#else -# define PNG_CONST -#endif - -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS - * on the compile line, then pick and choose which ones to define without - * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency) - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt is supported. It is turned off by default, to support old apps - * that malloc the png_text structure instead of calling png_set_text() - * and letting libpng malloc it. It will be turned on by default in - * libpng-1.3.0. - */ - -#ifndef PNG_iTXt_SUPPORTED -# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) -# define PNG_NO_READ_iTXt -# endif -# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) -# define PNG_NO_WRITE_iTXt -# endif -#endif - -/* The following support, added after version 1.0.0, can be turned off here en - * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility - * with old applications that require the length of png_struct and png_info - * to remain unchanged. - */ - -#ifdef PNG_LEGACY_SUPPORTED -# define PNG_NO_FREE_ME -# define PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_NO_READ_USER_CHUNKS -# define PNG_NO_READ_iCCP -# define PNG_NO_WRITE_iCCP -# define PNG_NO_READ_iTXt -# define PNG_NO_WRITE_iTXt -# define PNG_NO_READ_sCAL -# define PNG_NO_WRITE_sCAL -# define PNG_NO_READ_sPLT -# define PNG_NO_WRITE_sPLT -# define PNG_NO_INFO_IMAGE -# define PNG_NO_READ_RGB_TO_GRAY -# define PNG_NO_READ_USER_TRANSFORM -# define PNG_NO_WRITE_USER_TRANSFORM -# define PNG_NO_USER_MEM -# define PNG_NO_READ_EMPTY_PLTE -# define PNG_NO_MNG_FEATURES -# define PNG_NO_FIXED_POINT_SUPPORTED -#endif - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifndef PNG_NO_FREE_ME -# define PNG_FREE_ME_SUPPORTED -#endif - -#if defined(PNG_READ_SUPPORTED) - -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_READ_DITHER -# define PNG_READ_DITHER_SUPPORTED -# endif -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following line: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -/* Deprecated, will be removed from version 2.0.0. - Use PNG_MNG_FEATURES_SUPPORTED instead. */ -#ifndef PNG_NO_READ_EMPTY_PLTE -# define PNG_READ_EMPTY_PLTE_SUPPORTED -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_WRITE_SUPPORTED) - -# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant - encoders, but can cause trouble - if left undefined */ - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ -#ifndef PNG_NO_WRITE_EMPTY_PLTE -# define PNG_WRITE_EMPTY_PLTE_SUPPORTED -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef PNG_1_0_X -# ifndef PNG_NO_ERROR_NUMBERS -# define PNG_ERROR_NUMBERS_SUPPORTED -# endif -#endif /* PNG_1_0_X */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_STDIO -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 - even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */ -#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) -# ifndef PNG_ASSEMBLER_CODE_SUPPORTED -# define PNG_ASSEMBLER_CODE_SUPPORTED -# endif -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_MMX_CODE_SUPPORTED -# endif -#endif - -/* If you are sure that you don't need thread safety and you are compiling - with PNG_USE_PNGCCRD for an MMX application, you can define this for - faster execution. See pnggccrd.c. -#define PNG_THREAD_UNSAFE_OK -*/ - -#if !defined(PNG_1_0_X) -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#if !defined(PNG_1_0_X) -#ifndef PNG_SET_USER_LIMITS_SUPPORTED -#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) -# define PNG_SET_USER_LIMITS_SUPPORTED -#endif -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter - * how large, set these limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* These are currently experimental features, define them if you want */ - -/* very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ -/* -#define PNG_NO_POINTER_INDEXING -*/ - -/* These functions are turned off by default, as they will be phased out. */ -/* -#define PNG_USELESS_TESTS_SUPPORTED -#define PNG_CORRECT_PALETTE_SUPPORTED -*/ - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#if !defined(PNG_NO_READ_USER_CHUNKS) && \ - defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) -# define PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# ifdef PNG_NO_READ_UNKNOWN_CHUNKS -# undef PNG_NO_READ_UNKNOWN_CHUNKS -# endif -# ifdef PNG_NO_HANDLE_AS_UNKNOWN -# undef PNG_NO_HANDLE_AS_UNKNOWN -# endif -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* need the time information for reading tIME chunks */ -#if defined(PNG_tIME_SUPPORTED) -# if !defined(_WIN32_WCE) - /* "time.h" functions are not supported on WindowsCE */ -# include -# endif -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may - * want to have unsigned int for png_uint_32 instead of unsigned long. - */ - -typedef unsigned long png_uint_32; -typedef long png_int_32; -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -/* This is usually size_t. It is typedef'ed just in case you need it to - change (I'm not sure if you will or not, so I thought I'd be safe) */ -#ifdef PNG_SIZE_T - typedef PNG_SIZE_T png_size_t; -# define png_sizeof(x) png_convert_size(sizeof (x)) -#else - typedef size_t png_size_t; -# define png_sizeof(x) sizeof (x) -#endif - -/* The following is needed for medium model support. It cannot be in the - * PNG_INTERNAL section. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - defines FAR. (SJT) */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#if defined(FAR) -# if defined(M_I86MM) -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; - -#ifndef PNG_NO_STDIO -#if defined(_WIN32_WCE) -typedef HANDLE png_FILE_p; -#else -typedef FILE * png_FILE_p; -#endif -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -/* libpng typedefs for types in zlib. If zlib changes - * or another compression library is used, then change these. - * Eliminates need to change all the source files. - */ -typedef charf * png_zcharp; -typedef charf * FAR * png_zcharpp; -typedef z_stream FAR * png_zstreamp; - -/* - * Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif -/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. - * When building a static lib, default to no GLOBAL ARRAYS, but allow - * command-line override - */ -#if defined(__CYGWIN__) -# if !defined(PNG_STATIC) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -# else -# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# endif -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -#endif - -/* Do not use global arrays (helps with building DLL's) - * They are no longer used in libpng itself, since version 1.0.5c, - * but might be required for some pre-1.0.5c applications. - */ -#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL)) -# define PNG_USE_LOCAL_ARRAYS -# else -# define PNG_USE_GLOBAL_ARRAYS -# endif -#endif - -#if defined(__CYGWIN__) -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# if !defined(PNG_IMPEXP) - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in - VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# if !defined(PNG_IMPEXP) -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -#ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type -# endif -#endif - -/* User may want to use these so they are not in PNG_INTERNAL. Any library - * functions that are passed far data must be model independent. - */ - -#ifndef PNG_ABORT -# define PNG_ABORT() abort() -#endif - -#ifdef PNG_SETJMP_SUPPORTED -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) -#endif - -#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ -/* use this to make far-to-near assignments */ -# define CHECK 1 -# 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 -#else /* use the usual functions */ -# 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 -#endif -/* End of memory model independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - -#ifdef PNG_READ_SUPPORTED -/* Prior to libpng-1.0.9, this block was in pngasmrd.h */ -#if defined(PNG_INTERNAL) - -/* These are the default thresholds before the MMX code kicks in; if either - * rowbytes or bitdepth is below the threshold, plain C code is used. These - * can be overridden at runtime via the png_set_mmx_thresholds() call in - * libpng 1.2.0 and later. The values below were chosen by Intel. - */ - -#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT -# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ -#endif -#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT -# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ -#endif - -/* Set this in the makefile for VC++ on Pentium, not here. */ -/* Platform must be Pentium. Makefile must assemble and load pngvcrd.c . - * MMX will be detected at run time and used if present. - */ -#ifdef PNG_USE_PNGVCRD -# define PNG_HAVE_ASSEMBLER_COMBINE_ROW -# define PNG_HAVE_ASSEMBLER_READ_INTERLACE -# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW -#endif - -/* Set this in the makefile for gcc/as on Pentium, not here. */ -/* Platform must be Pentium. Makefile must assemble and load pnggccrd.c . - * MMX will be detected at run time and used if present. - */ -#ifdef PNG_USE_PNGGCCRD -# define PNG_HAVE_ASSEMBLER_COMBINE_ROW -# define PNG_HAVE_ASSEMBLER_READ_INTERLACE -# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW -#endif -/* - see pnggccrd.c for info about what is currently enabled */ - -#endif /* PNG_INTERNAL */ -#endif /* PNG_READ_SUPPORTED */ - -#endif /* PNGCONF_H */ - diff --git a/extern/libpng/include/png.c b/extern/libpng/include/png.c new file mode 100644 index 0000000000..7d09b0dbd2 --- /dev/null +++ b/extern/libpng/include/png.c @@ -0,0 +1,2362 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_5_2 Your_png_h_is_not_version_1_5_2; + +/* 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 + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + if (num_to_check > 8) + num_to_check = 8; + + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_alloc_size_t num_bytes; + + if (png_ptr == NULL) + return (NULL); + + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_alloc_size_t)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* 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)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +PNG_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer"); +} + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* 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 + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any iCCP entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +# endif + +# ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_const_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + 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))); + } + +# 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 */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.5.2 - March 31, 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.2 - March 31, 2011\ + Copyright (c) 1998-2011 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; +# endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_const_charp PNGAPI +png_get_libpng_ver(png_const_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +# endif +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +#ifdef PNG_READ_SUPPORTED +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + + return (inflateReset(&png_ptr->zstream)); +} +#endif /* PNG_READ_SUPPORTED */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32)PNG_LIBPNG_VER); +} + + + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + + return ((png_size_t)size); +} +# endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +# ifdef PNG_CHECK_cHRM_SUPPORTED + +int /* PRIVATE */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + + if (png_ptr == NULL) + return 0; + + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(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) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + + if (red_x > 100000L - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + + if (green_x > 100000L - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + + if (blue_x > 100000L - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +# endif /* PNG_CHECK_cHRM_SUPPORTED */ + +void /* PRIVATE */ +png_check_IHDR(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) + +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if (height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +# ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +# else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +# endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* 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 */ +#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] */ + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + { + 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; + } + } + + /* 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) + { + case PNG_FP_INTEGER + PNG_FP_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); + break; + + case PNG_FP_INTEGER + PNG_FP_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); + + else + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + break; + + case PNG_FP_INTEGER + PNG_FP_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); + + break; + case PNG_FP_INTEGER + PNG_FP_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SIGN: + goto PNG_FP_End; ** no sign in exponent */ + + /* case PNG_FP_FRACTION + PNG_FP_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); + break; + + case PNG_FP_FRACTION + PNG_FP_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). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_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); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +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); +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_READ_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1*/ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision*/ + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + exp_b10 = -exp_b10; + } + + cdigits = 0; + + while (exp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + exp_b10 % 10); + exp_b10 /= 10; + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, + png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000U) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16/*flag value*/; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* READ_SCAL */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) +png_fixed_point +png_fixed(png_structp png_ptr, double fp, png_const_charp text) +{ + double r = floor(100000 * fp + .5); + + if (r > 2147483647. || r < -2147483648.) + png_fixed_error(png_ptr, text); + + return (png_fixed_point)r; +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || \ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32 bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64 bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* A local convenience routine. */ +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, + * 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. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void /* PRIVATE */ +png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} +#endif /* CHECK_cHRM */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* 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. + * + * 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 + * 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. + */ +static png_uint_32 +png_8bit_l2[128] = +{ +# if PNG_DO_BC + for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; } +# endif + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 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. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +static png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return 7.99998 for the overflow (log 0) case - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return 0xffffffff; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + 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 + * 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. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * 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. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * 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: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +static png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return 0xffffffff; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28 bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + 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 + * 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 + * 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 + * top four fractional bits then multiplying in the remaining bits. + */ +static png_uint_32 +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. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#if PNG_DO_BC +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +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 */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +static png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* 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 + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +static png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* 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: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* 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_uint_16 /* PRIVATE */ +png_gamma_correct(png_structp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} + +/* 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). + * + * The caller is responsible for ensuring that the table gets cleaned up on + * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument + * should be somewhere that will be cleaned. + */ +static void +png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + /* Various values derived from 'shift': */ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int i; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_uint_16p sub_table = table[i] = + (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. + */ + if (png_gamma_significant(gamma_val)) + { + /* The old code would overflow at the end and this would cause the + * 'pow' function to return a result >1, resulting in an + * arithmetic error. This code follows the spec exactly; ig is + * the recovered input sample, it always has 8-16 bits. + * + * We want input * 65535/max, rounded, the arithmetic fits in 32 + * bits (unsigned) so long as max <= 32767. + */ + unsigned int j; + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* Inline the 'max' scaling operation: */ + double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); + sub_table[j] = (png_uint_16)d; +# else + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); +# endif + } + } + else + { + /* We must still build a table, but do it the fast way. */ + unsigned int j; + + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; + + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = (png_uint_16)ig; + } + } + } +} + +/* NOTE: this function expects the *inverse* of the overall gamma transformation + * required. + */ +static void +png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int i; + png_uint_32 last; + + png_uint_16pp table = *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 + * itself index by the high 8 bits of the value. + */ + for (i = 0; i < num; i++) + table[i] = (png_uint_16p)png_malloc(png_ptr, + 256 * png_sizeof(png_uint_16)); + + /* '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 + * 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 + * 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 */ + { + /* Find the corresponding maximum input 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); + + /* Adjust (round) to (16-shift) bits: */ + bound = (bound * max + 32768U)/65535U + 1U; + + while (last < bound) + { + table[last & (0xffU >> shift)][last >> (8U - shift)] = out; + last++; + } + } + + /* And fill in the final entries. */ + while (last < (num << 8)) + { + table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; + last++; + } +} + +/* 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. + */ +static void +png_build_8bit_table(png_structp png_ptr, png_bytepp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_8bit_correct(i, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_byte)i; +} + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->gamma)); + + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + 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 */ + } + else + { + png_byte shift, sig_bit; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + /* 16 bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256 entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits of + * the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & PNG_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 + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } + + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ + + png_ptr->gamma_shift = shift; + +#ifdef PNG_16BIT_SUPPORTED + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) +#endif + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#ifdef PNG_16BIT_SUPPORTED + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->gamma)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + 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_GAMMA */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/extern/libpng/include/png.h b/extern/libpng/include/png.h index 70acb20a2e..0af42b170e 100644 --- a/extern/libpng/include/png.h +++ b/extern/libpng/include/png.h @@ -1,26 +1,26 @@ /* png.h - header file for PNG reference library * - * libpng version 1.4.1 - February 25, 2010 - * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * libpng version 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.) * * This code is released under the libpng license (See LICENSE, below) * * 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.4.1 - February 25, 2010: Glenn - * See also "Contributing Authors", below. + * 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.2 - March 31, 2011: Glenn + * See also "Contributing Authors", below. * * Note about libpng version numbers: * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: * * source png.h png.h shared-lib * version string int version @@ -137,29 +137,40 @@ * 1.4.1beta01-03 14 10401 14.so.14.1[.0] * 1.4.1rc01 14 10401 14.so.14.1[.0] * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1rc02-04 14 10401 14.so.14.1[.0] * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 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] * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * +# 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 +# endif +# endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif /* * Added at libpng-1.2.8 @@ -408,13 +444,13 @@ * StringFileInfo block must contain a SpecialBuild string. */ -#ifdef PNG_USER_PRIVATEBUILD +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ # define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) #else # ifdef PNG_LIBPNG_SPECIALBUILD # define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) # else # define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) # endif @@ -427,20 +463,61 @@ extern "C" { #endif /* __cplusplus */ -/* This file is arranged in several sections. The first section contains - * structure and type definitions. The second section contains the external - * library functions, while the third has the internal library functions, - * which applications aren't expected to use directly. - */ - -/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */ -#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) /* Version information for C files, stored in png.c. This had better match * the version above. */ #define png_libpng_ver png_get_header_ver(NULL) -#endif /* PNG_NO_EXTERN */ +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* 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_2; /* 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 @@ -453,6 +530,7 @@ typedef struct png_color_struct png_byte blue; } png_color; typedef png_color FAR * png_colorp; +typedef PNG_CONST png_color FAR * png_const_colorp; typedef png_color FAR * FAR * png_colorpp; typedef struct png_color_16_struct @@ -464,6 +542,7 @@ typedef struct png_color_16_struct png_uint_16 gray; /* for use in grayscale files */ } png_color_16; typedef png_color_16 FAR * png_color_16p; +typedef PNG_CONST png_color_16 FAR * png_const_color_16p; typedef png_color_16 FAR * FAR * png_color_16pp; typedef struct png_color_8_struct @@ -475,6 +554,7 @@ typedef struct png_color_8_struct png_byte alpha; /* for alpha channel files */ } png_color_8; typedef png_color_8 FAR * png_color_8p; +typedef PNG_CONST png_color_8 FAR * png_const_color_8p; typedef png_color_8 FAR * FAR * png_color_8pp; /* @@ -490,6 +570,7 @@ typedef struct png_sPLT_entry_struct png_uint_16 frequency; } png_sPLT_entry; typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; /* When the depth of the sPLT palette is 8 bits, the color and alpha samples @@ -505,6 +586,7 @@ typedef struct png_sPLT_struct png_int_32 nentries; /* number of palette entries */ } png_sPLT_t; typedef png_sPLT_t FAR * png_sPLT_tp; +typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; #ifdef PNG_TEXT_SUPPORTED @@ -527,15 +609,14 @@ typedef struct png_text_struct png_charp text; /* comment, may be an empty string (ie "") or a NULL pointer */ png_size_t text_length; /* length of the text string */ -#ifdef PNG_iTXt_SUPPORTED png_size_t itxt_length; /* length of the itxt string */ png_charp lang; /* language code, 0-79 characters or a NULL pointer */ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more chars or a NULL pointer */ -#endif } png_text; typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_textp; typedef png_text FAR * FAR * png_textpp; #endif @@ -565,10 +646,11 @@ typedef struct png_time_struct png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ } png_time; typedef png_time FAR * png_timep; +typedef PNG_CONST png_time FAR * png_const_timep; typedef png_time FAR * FAR * png_timepp; #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) /* png_unknown_chunk is a structure to hold queued chunks for which there is * no specific support. The idea is that we can use this to queue * up private chunks for output even though the library doesn't actually @@ -585,312 +667,13 @@ typedef struct png_unknown_chunk_t } 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 -/* png_info is a structure that holds the information in a PNG file so - * that the application can find out the characteristics of the image. - * If you are reading the file, this structure will tell you what is - * in the PNG file. If you are writing the file, fill in the information - * you want to put into the PNG file, then call png_write_info(). - * The names chosen should be very close to the PNG specification, so - * consult that document for information about the meaning of each field. - * - * With libpng < 0.95, it was only possible to directly set and read the - * the values in the png_info_struct, which meant that the contents and - * order of the values had to remain fixed. With libpng 0.95 and later, - * however, there are now functions that abstract the contents of - * png_info_struct from the application, so this makes it easier to use - * libpng with dynamic libraries, and even makes it possible to use - * libraries that don't have all of the libpng ancillary chunk-handing - * functionality. - * - * In any case, the order of the parameters in png_info_struct should NOT - * be changed for as long as possible to keep compatibility with applications - * that use the old direct-access method with png_info_struct. - * - * The following members may have allocated storage attached that should be - * cleaned up before the structure is discarded: palette, trans, text, - * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, - * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these - * are automatically freed when the info structure is deallocated, if they were - * allocated internally by libpng. This behavior can be changed by means - * of the png_data_freer() function. - * - * More allocation details: all the chunk-reading functions that - * change these members go through the corresponding png_set_* - * functions. A function to clear these members is available: see - * png_free_data(). The png_set_* functions do not depend on being - * able to point info structure members to any of the storage they are - * passed (they make their own copies), EXCEPT that the png_set_text - * functions use the same storage passed to them in the text_ptr or - * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns - * functions do not make their own copies. - */ -typedef struct png_info_struct -{ - /* the following are necessary for every PNG file */ - png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels (from IHDR) */ - png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels (from IHDR) */ - png_uint_32 valid PNG_DEPSTRUCT; /* valid chunk data (see PNG_INFO_ - below) */ - png_size_t rowbytes PNG_DEPSTRUCT; /* bytes needed to hold an untransformed - row */ - png_colorp palette PNG_DEPSTRUCT; /* array of color values - (valid & PNG_INFO_PLTE) */ - png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in - "palette" (PLTE) */ - png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparent palette - color (tRNS) */ - png_byte bit_depth PNG_DEPSTRUCT; /* 1, 2, 4, 8, or 16 bits/channel - (from IHDR) */ - png_byte color_type PNG_DEPSTRUCT; /* see PNG_COLOR_TYPE_ below - (from IHDR) */ - /* The following three should have been named *_method not *_type */ - png_byte compression_type PNG_DEPSTRUCT; /* must be - PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type PNG_DEPSTRUCT; /* must be PNG_FILTER_TYPE_BASE - (from IHDR) */ - png_byte interlace_type PNG_DEPSTRUCT; /* One of PNG_INTERLACE_NONE, - PNG_INTERLACE_ADAM7 */ - - /* The following is informational only on read, and not used on writes. */ - png_byte channels PNG_DEPSTRUCT; /* number of data channels per - pixel (1, 2, 3, 4) */ - png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ - png_byte spare_byte PNG_DEPSTRUCT; /* to align the data, and for - future use */ - png_byte signature[8] PNG_DEPSTRUCT; /* magic bytes read by libpng - from start of file */ - - /* The rest of the data is optional. If you are reading, check the - * valid field to see if the information in these are valid. If you - * are writing, set the valid field to those chunks you want written, - * and initialize the appropriate fields below. - */ - -#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - /* The gAMA chunk describes the gamma characteristics of the system - * on which the image was created, normally in the range [1.0, 2.5]. - * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. - */ - float gamma PNG_DEPSTRUCT; /* gamma value of image, - if (valid & PNG_INFO_gAMA) */ -#endif - -#ifdef PNG_sRGB_SUPPORTED - /* GR-P, 0.96a */ - /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ - png_byte srgb_intent PNG_DEPSTRUCT; /* sRGB rendering intent - [0, 1, 2, or 3] */ -#endif - -#ifdef PNG_TEXT_SUPPORTED - /* The tEXt, and zTXt chunks contain human-readable textual data in - * uncompressed, compressed, and optionally compressed forms, respectively. - * The data in "text" is an array of pointers to uncompressed, - * null-terminated C strings. Each chunk has a keyword that describes the - * textual data contained in that chunk. Keywords are not required to be - * unique, and the text string may be empty. Any number of text chunks may - * be in an image. - */ - int num_text PNG_DEPSTRUCT; /* number of comments read/to write */ - int max_text PNG_DEPSTRUCT; /* current size of text array */ - png_textp text PNG_DEPSTRUCT; /* array of comments read/to write */ -#endif /* PNG_TEXT_SUPPORTED */ - -#ifdef PNG_tIME_SUPPORTED - /* The tIME chunk holds the last time the displayed image data was - * modified. See the png_time struct for the contents of this struct. - */ - png_time mod_time PNG_DEPSTRUCT; -#endif - -#ifdef PNG_sBIT_SUPPORTED - /* The sBIT chunk specifies the number of significant high-order bits - * in the pixel data. Values are in the range [1, bit_depth], and are - * only specified for the channels in the pixel data. The contents of - * the low-order bits is not specified. Data is valid if - * (valid & PNG_INFO_sBIT) is non-zero. - */ - png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in color channels */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ -defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The tRNS chunk supplies transparency data for paletted images and - * other image types that don't need a full alpha channel. There are - * "num_trans" transparency values for a paletted image, stored in the - * same order as the palette colors, starting from index 0. Values - * for the data are in the range [0, 255], ranging from fully transparent - * to fully opaque, respectively. For non-paletted images, there is a - * 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 PNG_DEPSTRUCT; /* alpha values for paletted - image */ - png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for - non-palette image */ -#endif - -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The bKGD chunk gives the suggested image background color if the - * display program does not have its own background color and the image - * is needs to composited onto a background before display. The colors - * in "background" are normally in the same color space/depth as the - * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. - */ - png_color_16 background PNG_DEPSTRUCT; -#endif - -#ifdef PNG_oFFs_SUPPORTED - /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards - * and downwards from the top-left corner of the display, page, or other - * application-specific co-ordinate space. See the PNG_OFFSET_ defines - * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. - */ - png_int_32 x_offset PNG_DEPSTRUCT; /* x offset on page */ - png_int_32 y_offset PNG_DEPSTRUCT; /* y offset on page */ - png_byte offset_unit_type PNG_DEPSTRUCT; /* offset units type */ -#endif - -#ifdef PNG_pHYs_SUPPORTED - /* The pHYs chunk gives the physical pixel density of the image for - * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ - * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. - */ - png_uint_32 x_pixels_per_unit PNG_DEPSTRUCT; /* horizontal pixel density */ - png_uint_32 y_pixels_per_unit PNG_DEPSTRUCT; /* vertical pixel density */ - png_byte phys_unit_type PNG_DEPSTRUCT; /* resolution type (see - PNG_RESOLUTION_ below) */ -#endif - -#ifdef PNG_hIST_SUPPORTED - /* The hIST chunk contains the relative frequency or importance of the - * various palette entries, so that a viewer can intelligently select a - * reduced-color palette, if required. Data is an array of "num_palette" - * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) - * is non-zero. - */ - png_uint_16p hist PNG_DEPSTRUCT; -#endif - -#ifdef PNG_cHRM_SUPPORTED - /* The cHRM chunk describes the CIE color characteristics of the monitor - * on which the PNG was created. This data allows the viewer to do gamut - * mapping of the input image to ensure that the viewer sees the same - * colors in the image as the creator. Values are in the range - * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float x_white PNG_DEPSTRUCT; - float y_white PNG_DEPSTRUCT; - float x_red PNG_DEPSTRUCT; - float y_red PNG_DEPSTRUCT; - float x_green PNG_DEPSTRUCT; - float y_green PNG_DEPSTRUCT; - float x_blue PNG_DEPSTRUCT; - float y_blue PNG_DEPSTRUCT; -#endif -#endif - -#ifdef PNG_pCAL_SUPPORTED - /* The pCAL chunk describes a transformation between the stored pixel - * values and original physical data values used to create the image. - * The integer range [0, 2^bit_depth - 1] maps to the floating-point - * range given by [pcal_X0, pcal_X1], and are further transformed by a - * (possibly non-linear) transformation function given by "pcal_type" - * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ - * defines below, and the PNG-Group's PNG extensions document for a - * complete description of the transformations and how they should be - * implemented, and for a description of the ASCII parameter strings. - * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. - */ - png_charp pcal_purpose PNG_DEPSTRUCT; /* pCAL chunk description string */ - png_int_32 pcal_X0 PNG_DEPSTRUCT; /* minimum value */ - png_int_32 pcal_X1 PNG_DEPSTRUCT; /* maximum value */ - png_charp pcal_units PNG_DEPSTRUCT; /* Latin-1 string giving physical - units */ - png_charpp pcal_params PNG_DEPSTRUCT; /* ASCII strings containing - parameter values */ - png_byte pcal_type PNG_DEPSTRUCT; /* equation type - (see PNG_EQUATION_ below) */ - png_byte pcal_nparams PNG_DEPSTRUCT; /* number of parameters given - in pcal_params */ -#endif - -/* New members added in libpng-1.0.6 */ - png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is - responsible for freeing */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) - /* Storage for unknown chunks that the library doesn't recognize. */ - png_unknown_chunkp unknown_chunks PNG_DEPSTRUCT; - png_size_t unknown_chunks_num PNG_DEPSTRUCT; -#endif - -#ifdef PNG_iCCP_SUPPORTED - /* iCCP chunk data. */ - png_charp iccp_name PNG_DEPSTRUCT; /* profile name */ - png_charp iccp_profile PNG_DEPSTRUCT; /* International Color Consortium - profile data */ - /* Note to maintainer: should be png_bytep */ - png_uint_32 iccp_proflen PNG_DEPSTRUCT; /* ICC profile data length */ - png_byte iccp_compression PNG_DEPSTRUCT; /* Always zero */ -#endif - -#ifdef PNG_sPLT_SUPPORTED - /* Data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes PNG_DEPSTRUCT; - png_uint_32 splt_palettes_num PNG_DEPSTRUCT; -#endif - -#ifdef PNG_sCAL_SUPPORTED - /* The sCAL chunk describes the actual physical dimensions of the - * subject matter of the graphic. The chunk contains a unit specification - * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel - * in the image. This external representation is converted to double - * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. - */ - png_byte scal_unit PNG_DEPSTRUCT; /* unit of physical scale */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - double scal_pixel_width PNG_DEPSTRUCT; /* width of one pixel */ - double scal_pixel_height PNG_DEPSTRUCT; /* height of one pixel */ -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_charp scal_s_width PNG_DEPSTRUCT; /* string containing height */ - png_charp scal_s_height PNG_DEPSTRUCT; /* string containing width */ -#endif -#endif - -#ifdef PNG_INFO_IMAGE_SUPPORTED - /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) - non-zero */ - /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers PNG_DEPSTRUCT; /* the image bits */ -#endif - -#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) - png_fixed_point int_gamma PNG_DEPSTRUCT; /* gamma of image, - if (valid & PNG_INFO_gAMA) */ -#endif - -#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) - png_fixed_point int_x_white PNG_DEPSTRUCT; - png_fixed_point int_y_white PNG_DEPSTRUCT; - png_fixed_point int_x_red PNG_DEPSTRUCT; - png_fixed_point int_y_red PNG_DEPSTRUCT; - png_fixed_point int_x_green PNG_DEPSTRUCT; - png_fixed_point int_y_green PNG_DEPSTRUCT; - png_fixed_point int_x_blue PNG_DEPSTRUCT; - png_fixed_point int_y_blue PNG_DEPSTRUCT; -#endif - -} png_info; - +typedef struct png_info_def png_info; typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_infop; typedef png_info FAR * FAR * png_infopp; /* Maximum positive integer used in PNG is (2^31)-1 */ @@ -898,6 +681,12 @@ typedef png_info FAR * FAR * png_infopp; #define PNG_UINT_32_MAX ((png_uint_32)(-1)) #define PNG_SIZE_MAX ((png_size_t)(-1)) +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 + /* These describe the color_type field in png_info. */ /* color type masks */ #define PNG_COLOR_MASK_PALETTE 1 @@ -992,11 +781,11 @@ typedef png_info FAR * FAR * png_infopp; */ typedef struct png_row_info_struct { - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ png_byte pixel_depth; /* bits per pixel (depth * channels) */ } png_row_info; @@ -1007,46 +796,74 @@ typedef png_row_info FAR * FAR * png_row_infopp; * 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 * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. + * user read/write data functions. Note that the 'write' function must not + * 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 void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((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 void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, - png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((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 void (PNGAPI *png_user_transform_ptr) PNGARG((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 int (PNGAPI *png_user_chunk_ptr) PNGARG((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 void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); #endif + #ifdef PNG_SETJMP_SUPPORTED /* This must match the function definition in , and the * application must include this before png.h to obtain the definition - * of jmp_buf. + * 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 + * 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 void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); +typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), + PNG_PTR_NORETURN); #endif /* Transform masks for the high-level interface */ @@ -1074,442 +891,85 @@ typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); #define PNG_FLAG_MNG_FILTER_64 0x04 #define PNG_ALL_MNG_FEATURES 0x05 -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. +/* 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. */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ - png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto - function. */ -#endif - png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing - errors and aborting */ - png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing - warnings */ - png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for - error functions */ - png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing - output data */ - png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading - input data */ - png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct - for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read - transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write - transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct - for user transform */ - png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user - transformed pixels */ - png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user - transformed pixels */ -#endif -#endif - - png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in - the PNG file */ - png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various - things to libpng */ - png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations - to perform */ - - z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression - structure (below) */ - png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ - png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ - int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ - int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ - int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window - bits */ - int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory - level */ - int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression - strategy */ - - png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ - png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ - png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ - png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ - png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ -#if 0 /* Replaced with the following in libpng-1.4.1 */ - png_size_t irowbytes PNG_DEPSTRUCT; -#endif -/* Added in libpng-1.4.1 */ -#ifdef PNG_USER_LIMITS_SUPPORTED - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. - * We will change the typedef from png_size_t to png_alloc_size_t - * in libpng-1.6.0 - */ - png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; -#endif - png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced - row in pixels */ - png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ - png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous - (unfiltered) row */ - png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row - when filtering */ - png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row - when filtering */ - png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row - when filtering */ - png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row - when filtering */ - png_row_info row_info PNG_DEPSTRUCT; /* used for transformation - routines */ - - png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ - png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ - png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ - png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in - palette */ - png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ - png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current - chunk */ - png_byte compression PNG_DEPSTRUCT; /* file compression type - (always 0) */ - png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ - png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, - PNG_INTERLACE_ADAM7 */ - png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ - png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see - PNG_FILTER_ below ) */ - png_byte color_type PNG_DEPSTRUCT; /* color type of file */ - png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ - png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ - png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ - png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ - png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ - png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from - start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel - expansion */ -#endif - -#ifdef PNG_bKGD_SUPPORTED - png_byte background_gamma_type PNG_DEPSTRUCT; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma PNG_DEPSTRUCT; -# endif - png_color_16 background PNG_DEPSTRUCT; /* background color in - screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized - to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing - output */ - png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, - 0 - no flush */ - png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since - last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits - 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma PNG_DEPSTRUCT; /* file gamma value */ - float screen_gamma PNG_DEPSTRUCT; /* screen gamma value - (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit - depth files */ - png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ - png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit - depth files */ - png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to - screen */ - png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each - available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit - tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for - paletted files */ - png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for - non-paletted files */ -#endif - - png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each - row is decoded */ - png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each - row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header - data fully read */ - png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each - prog. row is decoded */ - png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image - is complete */ - png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in - save_buffer */ - png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously - read data */ - png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in - current_buffer */ - png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently - used data */ - png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input - chunk */ - png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in - input data */ - png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now - in save_buffer */ - png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of - save_buffer */ - png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of - available input data */ - png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now - in current_buffer */ - int process_mode PNG_DEPSTRUCT; /* what push library - is currently doing */ - int cur_palette PNG_DEPSTRUCT; /* current push library - palette index */ - -# ifdef PNG_TEXT_SUPPORTED - png_size_t current_text_size PNG_DEPSTRUCT; /* current size of - text input data */ - png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left - to read in input */ - png_charp current_text PNG_DEPSTRUCT; /* current text chunk - buffer */ - png_charp current_text_ptr PNG_DEPSTRUCT; /* current location - in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr PNG_DEPSTRUCT; - png_bytep offset_table PNG_DEPSTRUCT; - png_uint_16 offset_table_number PNG_DEPSTRUCT; - png_uint_16 offset_table_count PNG_DEPSTRUCT; - png_uint_16 offset_table_count_free PNG_DEPSTRUCT; -#endif - -#ifdef PNG_READ_DITHER_SUPPORTED - png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for dithering */ - png_bytep dither_index PNG_DEPSTRUCT; /* index translation for palette - files */ -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row - filter selection */ - png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights - for previous rows */ - png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of - previous row(s) */ - png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous - line(s) */ - png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for - previous line(s) */ - png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter - calculation cost */ - png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter - calculation cost */ -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - - png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is - responsible for freeing */ - -#ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr PNG_DEPSTRUCT; - png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read - chunk handler */ -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int num_chunk_list PNG_DEPSTRUCT; - png_bytep chunk_list PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status PNG_DEPSTRUCT; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_byte filter_type PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.0 */ - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for - mem functions */ - png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for - allocating memory */ - png_free_ptr free_fn PNG_DEPSTRUCT; /* function for - freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - -#ifdef PNG_READ_DITHER_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort PNG_DEPSTRUCT; /* working sort array */ - png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original - index currently is - in the palette */ - png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index - points to this - palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type PNG_DEPSTRUCT; - -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max PNG_DEPSTRUCT; - png_uint_32 user_height_max PNG_DEPSTRUCT; - /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown - * chunks that can be stored (0 means unlimited). - */ - png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED - /* Storage for unknown chunk that the library doesn't recognize. */ - png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.26 */ - png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; - png_uint_32 old_prev_row_size PNG_DEPSTRUCT; - -/* New member added in libpng-1.2.30 */ - png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ - -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state PNG_DEPSTRUCT; -#endif -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_4_1; +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; -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the * full explanation, see example.c for the summary. This just provides * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes */ /* Returns the version number of the library */ -extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); /* Tell lib we have already handled the first magic bytes. * Handling more than 8 bytes from the beginning of the file is an error. */ -extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a * PNG file. Returns zero if the supplied bytes match the 8-byte PNG * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); +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 + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) /* Allocate and initialize png_ptr struct for reading, and any other memory. */ -extern PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; +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_ALLOCATED); /* Allocate and initialize png_ptr struct for writing, and any other memory */ -extern PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; +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_ALLOCATED); -extern PNG_EXPORT(png_size_t,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); -extern PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_size_t size)); +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 * match up. @@ -1522,284 +982,316 @@ extern PNG_EXPORT(void,png_set_compression_buffer_size) * allocated by the library - the call will return NULL on a mismatch * indicating an ABI mismatch. */ -extern PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) - PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t - jmp_buf_size)); +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))) + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) #else # define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) #endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); +#ifdef PNG_READ_SUPPORTED /* Reset the compression stream */ -extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif /* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ #ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((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_ALLOCATED; -extern PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((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_ALLOCATED; +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_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_ALLOCATED); #endif /* Write the PNG file signature. */ -extern PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); /* Write a PNG chunk - size, type, (optional) data, CRC. */ -extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); +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. */ -extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); +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(). */ -extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); /* Allocate and initialize the info structure */ -extern PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)) PNG_ALLOCATED; +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); -extern PNG_EXPORT(void,png_info_init_3) PNGARG((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. */ -extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the information before the actual image data. */ -extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); #endif #ifdef PNG_TIME_RFC1123_SUPPORTED -extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); #endif #ifdef PNG_CONVERT_tIME_SUPPORTED /* Convert from a struct tm to png_time */ -extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); +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() */ -extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); +PNG_EXPORT(25, void, png_convert_from_time_t, + (png_timep ptime, time_t ttime)); #endif /* PNG_CONVERT_tIME_SUPPORTED */ #ifdef PNG_READ_EXPAND_SUPPORTED /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +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. */ -extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); #endif #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand the grayscale to 24-bit RGB if necessary. */ -extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); +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, + 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 -extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) /* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); +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 +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); +PNG_EXPORT(40, void, png_set_add_alpha, + (png_structp png_ptr, png_uint_32 filler, + int flags)); #endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) /* Swap bytes in 16-bit depth files. */ -extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); #endif #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) /* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ defined(PNG_WRITE_PACKSWAP_SUPPORTED) /* Swap packing order of pixels in bytes. */ -extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) /* Converts files to legal bit depths. */ -extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p + true_bits)); #endif #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) /* Invert monochrome files */ -extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +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. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); +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, + int need_expand, png_fixed_point background_gamma)); #endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 #endif #ifdef PNG_READ_16_TO_8_SUPPORTED /* Strip the second byte of information from a 16-bit depth file. */ -extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); #endif -#ifdef PNG_READ_DITHER_SUPPORTED -/* Turn on dithering, and reduce the palette to the number of colors +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors * available. */ -extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_dither)); +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, + int full_quantize)); #endif #ifdef PNG_READ_GAMMA_SUPPORTED -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +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)); +#endif #ifdef PNG_WRITE_FLUSH_SUPPORTED /* Set how many lines between output flushes - 0 for no flushing */ -extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); /* Flush the current PNG output buffer */ -extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); #endif /* Optional update palette with requested transformations */ -extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); /* Optional call to update the users info structure */ -extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read one or more rows of image data. */ -extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +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. */ -extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, + png_bytep display_row)); #endif #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the whole image into memory at once. */ -extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); #endif /* Write a row of image data */ -extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); -/* Write a few rows of image data */ -extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * 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_uint_32 num_rows)); /* Write the image data */ -extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); /* Write the end of the PNG file. */ -extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the end of the PNG file. */ -extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +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 */ -extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_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 */ -extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_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 */ -extern PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_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 */ -extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); -/* Values for png_set_crc_action() to say how to handle CRC errors in +/* 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, @@ -1826,8 +1318,8 @@ extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, /* Set the filtering method(s) used by libpng. Currently, the only valid * value for "method" is 0. */ -extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); +PNG_EXPORT(67, void, png_set_filter, + (png_structp png_ptr, int method, int filters)); /* Flags for png_set_filter() to say which filters to use. The flags * are chosen so that they don't conflict with real filter types @@ -1882,11 +1374,13 @@ extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, * the weights and costs are set to 1.0, this degenerates the WEIGHTED method * to the UNWEIGHTED method, but with added encoding time/computation. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif +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, + 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 */ /* Heuristic used for row filter selection. These defines should NOT be @@ -1904,34 +1398,33 @@ extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, * for PNG images, and do considerably fewer caclulations. In the future, * these values may not correspond directly to the zlib compression levels. */ -extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); -extern PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); -extern PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); -extern PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); -extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); +PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, + int method)); /* These next functions are called for input/output, memory, and error * 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 - * different manner by calling png_set_???_fn(). See libpng.txt for + * different manner by calling png_set_???_fn(). See libpng-manual.txt for * more information. */ #ifdef PNG_STDIO_SUPPORTED /* Initialize the input/output for the PNG file to the default functions. */ -extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, - png_FILE_p fp)); +PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); #endif /* Replace the (error and abort), and warning functions with user @@ -1942,11 +1435,12 @@ extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, * default function will be used. */ -extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); +PNG_EXPORT(75, void, png_set_error_fn, + (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 */ -extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); /* Replace the default data output functions with a user supplied one(s). * If buffered output is not used, then output_flush_fn can be set to NULL. @@ -1958,101 +1452,137 @@ extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); * default flush function, which uses the standard *FILE structure, will * be used. */ -extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); +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. */ -extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); +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 */ -extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); -extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr write_row_fn)); +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). */ -extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +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 */ -extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); #endif #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); +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 -extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); #endif -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp - png_ptr, png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); +#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, + int user_transform_channels)); /* Return the user pointer associated with the user transform functions */ -extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* 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 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 -extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((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 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED /* Sets the function callbacks for the push reader, and a pointer to a * user-defined structure available to the callback functions. */ -extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((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)); +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 */ -extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); /* Function to be called when data becomes available */ -extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); -/* Function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. */ -extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * 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_bytep old_row, png_const_bytep new_row)); #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ -extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); /* Added at libpng version 1.4.0 */ -extern PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); /* Added at libpng version 1.2.4 */ -extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; +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() */ -extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); /* Free data that was allocated internally */ -extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); +PNG_EXPORT(98, void, png_free_data, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); + /* Reassign responsibility for freeing existing data, whether allocated * by libpng or by the application */ -extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); +PNG_EXPORT(99, void, png_data_freer, + (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); + /* Assignments for png_data_freer */ #define PNG_DESTROY_WILL_FREE_DATA 1 #define PNG_SET_WILL_FREE_DATA 1 @@ -2073,46 +1603,56 @@ extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, #define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; -extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp 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 -#ifndef PNG_NO_ERROR_TEXT +#ifdef PNG_ERROR_TEXT_SUPPORTED /* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); /* The same, but the chunk name is prepended to the error string. */ -extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); #else /* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); #endif /* Non-fatal error in libpng. Can continue, but may have a problem. */ -extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); +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. */ -extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, + png_const_charp warning_message)); #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. */ -extern PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); /* Same, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); -extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp - png_ptr, int allowed)); +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif #endif /* The png_set_ functions are for storing values in the png_info_struct. @@ -2128,258 +1668,268 @@ extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp * png_info_struct. */ /* Returns "flag" if chunk data is valid in info_ptr. */ -extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -extern PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_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 /* Returns row_pointers, which is an array of pointers to scanlines that was * returned from png_read_png(). */ -extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); /* Set row_pointers, which is an array of pointers to scanlines for use * by png_write_png(). */ -extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); #endif /* Returns number of color channels in image. */ -extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); #ifdef PNG_EASY_ACCESS_SUPPORTED /* Returns image width in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_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. */ -extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_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. */ -extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image color_type. */ -extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); /* Returns image filter_type. */ -extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); /* Returns image interlace_type. */ -extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); /* Returns image compression_type. */ -extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_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. */ -extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif +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_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); #endif /* PNG_EASY_ACCESS_SUPPORTED */ /* Returns pointer to signature string read from PNG header */ -extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); #ifdef PNG_bKGD_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); #endif #ifdef PNG_bKGD_SUPPORTED -extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); +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 -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((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)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((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)); +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_fixed_point *int_blue_y)); #endif #endif #ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM) PNGARG((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)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((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 +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, + 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_point int_blue_y)); #endif #ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (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, + png_fixed_point *int_file_gamma)); #endif #ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); +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_infop info_ptr, png_fixed_point int_file_gamma)); #endif #ifdef PNG_hIST_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); #endif #ifdef PNG_hIST_SUPPORTED -extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); #endif -extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((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(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, + int *interlace_method, int *compression_method, int *filter_method)); -extern PNG_EXPORT(void,png_set_IHDR) PNGARG((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, + int interlace_method, int compression_method, int filter_method)); #ifdef PNG_oFFs_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (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 -extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); +PNG_EXPORT(146, void, png_set_oFFs, + (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 -extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (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, + png_charp *units, png_charpp *params)); #endif #ifdef PNG_pCAL_SUPPORTED -extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); +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, + int nparams, png_const_charp units, png_charpp params)); #endif #ifdef PNG_pHYs_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (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 -extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); #endif -extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); -extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_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_const_colorp palette, int num_palette)); #ifdef PNG_sBIT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); #endif #ifdef PNG_sBIT_SUPPORTED -extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); #endif #ifdef PNG_sRGB_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); #endif #ifdef PNG_sRGB_SUPPORTED -extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); +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_infop info_ptr, int srgb_intent)); #endif #ifdef PNG_iCCP_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ +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_uint_32 *proflen)); #endif #ifdef PNG_iCCP_SUPPORTED -extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ +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_uint_32 proflen)); #endif #ifdef PNG_sPLT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); #endif #ifdef PNG_sPLT_SUPPORTED -extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); +PNG_EXPORT(161, void, png_set_sPLT, + (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 */ -extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); +PNG_EXPORT(162, png_uint_32, png_get_text, + (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, @@ -2390,59 +1940,64 @@ extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, */ #ifdef PNG_TEXT_SUPPORTED -extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); #endif #ifdef PNG_tIME_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); #endif #ifdef PNG_tIME_SUPPORTED -extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); #endif #ifdef PNG_tRNS_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans_alpha, int num_trans, - png_color_16p trans_color)); +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (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_const_color_16p trans_color)); #endif #ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (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, + * 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 *height)); #endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (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_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); #endif /* PNG_sCAL_SUPPORTED */ -#ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED /* Provide a list of chunks and how they are to be handled, if the built-in handling or default unknown chunk handling is not desired. Any chunks not @@ -2453,48 +2008,49 @@ extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, = 2: keep only if safe-to-copy = 3: keep even if unsafe-to-copy */ -extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (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_const_bytep chunk_name)); #endif #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +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_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, * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ -extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); +PNG_EXPORT(177, void, png_set_invalid, + (png_structp png_ptr, png_infop info_ptr, int mask)); #ifdef PNG_INFO_IMAGE_SUPPORTED /* The "params" pointer is currently not used and is for future expansion. */ -extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); +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, + int transforms, png_voidp params)); #endif -extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); #ifdef PNG_MNG_FEATURES_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, + png_uint_32 mng_features_permitted)); #endif /* For use in png_set_keep_unknown, added to version 1.2.6 */ @@ -2507,74 +2063,136 @@ extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp * messages before passing them to the error or warning handler. */ #ifdef PNG_ERROR_NUMBERS_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); #endif /* Added in libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED -extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((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 */ -extern PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp - png_ptr, png_uint_32 user_chunk_cache_max)); -extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) - PNGARG((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 */ -extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp - png_ptr, png_alloc_size_t user_chunk_cache_max)); -extern PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) - PNGARG((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)); #endif -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_ptr)); +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_structp png_ptr, png_const_infop info_ptr)); +#endif -PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_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_structp png_ptr, png_const_infop info_ptr)); +#endif -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ +# ifdef PNG_pHYs_SUPPORTED +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 */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ /* Added in libpng-1.4.0 */ #ifdef PNG_IO_STATE_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); -extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) - PNGARG((png_structp png_ptr)); +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structp png_ptr)); /* The flags returned by png_get_io_state() are the following: */ -#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -#define PNG_IO_READING 0x0001 /* currently reading */ -#define PNG_IO_WRITING 0x0002 /* currently writing */ -#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ #endif /* ?PNG_IO_STATE_SUPPORTED */ -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* 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)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) #ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED /* With these routines we avoid an integer divide, which will be slower on @@ -2589,7 +2207,7 @@ extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] */ - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ # define png_composite(composite, fg, alpha, bg) \ { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ @@ -2607,75 +2225,80 @@ extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) #else /* Standard method using integer division */ -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) # define png_composite_16(composite, fg, alpha, bg) \ (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) #endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +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_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +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, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + #ifdef PNG_USE_READ_MACROS /* Inline macros to do direct reads of bytes from the input buffer. * The png_get_int_32() routine assumes we are using two's complement * format for negative values, which is almost certainly true. */ -/* We could make special-case BIG_ENDIAN macros that do direct reads here */ # define png_get_uint_32(buf) \ (((png_uint_32)(*(buf)) << 24) + \ ((png_uint_32)(*((buf) + 1)) << 16) + \ ((png_uint_32)(*((buf) + 2)) << 8) + \ ((png_uint_32)(*((buf) + 3)))) + + /* 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. + */ # define png_get_uint_16(buf) \ - (((png_uint_32)(*(buf)) << 8) + \ - ((png_uint_32)(*((buf) + 1)))) -#ifdef PNG_GET_INT_32_SUPPORTED + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + # define png_get_int_32(buf) \ - (((png_int_32)(*(buf)) << 24) + \ - ((png_int_32)(*((buf) + 1)) << 16) + \ - ((png_int_32)(*((buf) + 2)) << 8) + \ - ((png_int_32)(*((buf) + 3)))) + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) #endif -#else -extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); -#ifdef PNG_GET_INT_32_SUPPORTED -extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); -#endif -#endif -extern PNG_EXPORT(png_uint_32,png_get_uint_31) - PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -extern PNG_EXPORT(void,png_save_uint_32) - PNGARG((png_bytep buf, png_uint_32 i)); -extern PNG_EXPORT(void,png_save_int_32) - PNGARG((png_bytep buf, png_int_32 i)); - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs */ -extern PNG_EXPORT(void,png_save_uint_16) - PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -/* ************************************************************************* */ - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(221); +#endif #ifdef __cplusplus } diff --git a/extern/libpng/include/pngconf.h b/extern/libpng/include/pngconf.h index 4aacf9c7ac..c82fa5866c 100644 --- a/extern/libpng/include/pngconf.h +++ b/extern/libpng/include/pngconf.h @@ -1,9 +1,9 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.4.1 - February 25, 2010 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * libpng version 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.) * @@ -22,282 +22,57 @@ #ifndef PNGCONF_H #define PNGCONF_H -#ifndef PNG_NO_LIMITS_H -# include -#endif - -/* Added at libpng-1.2.9 */ - -/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" - * script. +#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). */ -#ifdef PNG_CONFIGURE_LIBPNG -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif -#endif - -/* - * Added at libpng-1.2.8 - * - * PNG_USER_CONFIG has to be defined on the compiler command line. This - * includes the resource compiler for Windows DLL configurations. - */ -#ifdef PNG_USER_CONFIG -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD -# endif -# include "pngusr.h" -#endif - -/* - * If you create a private DLL you need to define in "pngusr.h" the followings: - * #define PNG_USER_PRIVATEBUILD - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng13gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - -#ifdef __STDC__ -# ifdef SPECIALBUILD -# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ - are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +# ifndef PNG_NO_LIMITS_H +# include # endif -# ifdef PRIVATEBUILD -# pragma message("PRIVATEBUILD is deprecated.\ - Use PNG_USER_PRIVATEBUILD instead.") -# define PNG_USER_PRIVATEBUILD PRIVATEBUILD -# endif -#endif /* __STDC__ */ - -/* End of material added to libpng-1.2.8 */ - -#ifndef PNG_VERSION_INFO_ONLY - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. +/* 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. */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled in 1.4.0. */ -#ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -#else -# ifndef PNG_BENIGN_ERRORS_SUPPORTED -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) -# define PNG_WARNINGS_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) -# define PNG_ERROR_TEXT_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) -# define PNG_CHECK_cHRM_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_ALIGNED_MEMORY_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#ifndef PNG_NO_MNG_FEATURES -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.4.0beta49 for testing (this test is no longer used - in libpng and png_calloc() is always present) - */ -#define PNG_CALLOC_SUPPORTED - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO. - */ -#ifdef __CYGWIN__ -# ifdef ALL_STATIC -# ifdef PNG_BUILD_DLL -# undef PNG_BUILD_DLL -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# ifndef PNG_STATIC -# define PNG_STATIC -# endif +# ifdef BSD +# include # else -# ifdef PNG_BUILD_DLL -# ifdef PNG_STATIC -# undef PNG_STATIC -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# else -# ifdef PNG_STATIC -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# else -# ifndef PNG_USE_DLL -# define PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# endif -# endif +# include # endif -#endif -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO +/* For png_FILE_p - this provides the standard definition of a + * FILE */ - -#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) -# define PNG_STDIO_SUPPORTED -#endif - - -#ifdef PNG_BUILD_DLL -# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) -# define PNG_NO_CONSOLE_IO -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else +# ifdef PNG_STDIO_SUPPORTED # include # endif - -#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) -# define PNG_CONSOLE_IO_SUPPORTED #endif -/* This macro protects us against machines that don't have function +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro protects us against machines that don't have function * prototypes (ie K&R style headers). If your compiler does not handle * function prototypes, define this macro and use the included ansi2knr. * I've always been able to use _NO_PROTO as the indicator, but you may @@ -306,128 +81,399 @@ */ #ifndef PNGARG -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else +# ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +# else -#ifdef _NO_PROTO -# define PNGARG(arglist) () -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ +# ifdef _NO_PROTO +# define PNGARG(arglist) () +# else +# define PNGARG(arglist) arglist +# endif /* _NO_PROTO */ -#endif /* OF */ +# endif /* OF */ #endif /* PNGARG */ -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64) ) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* The default for PNG_IMPEXP depends on whether the library is + * being built or used. + */ +#ifndef PNG_IMPEXP +# ifdef PNGLIB_BUILD + /* Building the library */ +# if (defined(DLL_EXPORT)/*from libtool*/ ||\ + defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ + defined(_USRDLL) ||\ + defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) + /* Building a DLL. */ +# define PNG_IMPEXP PNG_DLL_EXPORT +# endif /* DLL */ +# else + /* Using the library */ +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP # endif #endif -/* Enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) -# include +/* 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 +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args #endif -/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ -#if !defined(PNG_NO_SETJMP) && \ - !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type #endif -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, 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_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. * - * You can bypass this test if you know that your application uses exactly - * the same setjmp.h that was included when libpng was built. Only define - * PNG_SKIP_SETJMP_CHECK while building your application, prior to the - * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK - * while building a separate libpng library for general use. + * Added at libpng-1.2.41. */ -# ifndef PNG_SKIP_SETJMP_CHECK -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __pngconf.h__ in libpng already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ -# endif /* PNG_SKIP_SETJMP_CHECK */ +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif - /* Include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# ifdef _BSD_SOURCE -# undef _BSD_SOURCE +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# 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 + /* It's not enough to have the compiler be the correct compiler at + * this point - it's necessary for the library (which defines + * the type of the library longjmp) to also be the GNU library. + * This is because many systems use the GNU compiler with a + * non-GNU libc implementation. Min/GW headers are also compatible + * with GCC as well as uclibc, so it seems best to exclude known + * problem libcs here rather than just including known libcs. + * + * NOTE: this relies on the only use of PNG_PTR_NORETURN being with + * the system longjmp. If the same type is used elsewhere then this + * will need to be changed. + */ +# if !defined(__CYGWIN__) +# define PNG_PTR_NORETURN __attribute__((__noreturn__)) # endif -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) # endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ -#ifdef BSD -# include -#else -# include + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# 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 \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# endif /* PNGLIB_BUILD */ +# endif /* __GNUC__ */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# 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) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# 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 +# endif /* PNGLIB_BUILD */ +# endif /* _MSC_VER */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ #endif - -/* Other defines for things like memory and the like can go here. */ - -/* This controls how fine the dithering gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with dithering quality can decrease some or all of these. - */ -#ifndef PNG_DITHER_RED_BITS -# define PNG_DITHER_RED_BITS 5 +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ #endif -#ifndef PNG_DITHER_GREEN_BITS -# define PNG_DITHER_GREEN_BITS 5 +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ #endif -#ifndef PNG_DITHER_BLUE_BITS -# define PNG_DITHER_BLUE_BITS 5 +#ifndef PNG_PTR_NORETURN +# define PNG_PTR_NORETURN /* This function does not return */ #endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ #endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 +#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 +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif #endif /* The following uses const char * instead of char * for error * and warning message functions, so some compilers won't complain. * If you do not want to use const, define PNG_NO_CONST here. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. */ - #ifndef PNG_CONST # ifndef PNG_NO_CONST # define PNG_CONST const @@ -436,645 +482,6 @@ # endif #endif -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, - * then pick and choose which ones to define without having to edit this - * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in - * 1.4.0) - */ - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifdef PNG_READ_SUPPORTED - -/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -#if 0 /* removed from libpng-1.4.0 */ -# ifndef PNG_NO_READ_DITHER -# define PNG_READ_DITHER_SUPPORTED -# endif -#endif /* 0 */ -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following define: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ - -/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_SEQUENTIAL_READ) && \ - !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ - !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) -# define PNG_SEQUENTIAL_READ_SUPPORTED -#endif - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ - defined(PNG_READ_pCAL_SUPPORTED) -# ifndef PNG_GET_INT_32_SUPPORTED -# define PNG_GET_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#ifdef PNG_WRITE_SUPPORTED - -/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* This is not required for PNG-compliant encoders, but can cause - * trouble if left undefined - */ -# define PNG_WRITE_INTERLACING_SUPPORTED -#endif - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ - defined(PNG_WRITE_pCAL_SUPPORTED) -# ifndef PNG_SAVE_INT_32_SUPPORTED -# define PNG_SAVE_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#define PNG_NO_ERROR_NUMBERS - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* Added at libpng-1.2.0 */ -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif - -/* Added at libpng-1.2.6 */ -#ifndef PNG_NO_SET_USER_LIMITS -# ifndef PNG_SET_USER_LIMITS_SUPPORTED -# define PNG_SET_USER_LIMITS_SUPPORTED -# endif - /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# endif - /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_LIMITS_SUPPORTED -# ifndef PNG_NO_USER_LIMITS -# define PNG_USER_LIMITS_SUPPORTED -# endif -#endif - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter - * how large, set these two limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* Added at libpng-1.2.43. To accept all valid PNGs no matter - * how large, set these two limits to 0. - */ -#ifndef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 0 -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 0 -#endif - -/* Added at libpng-1.4.0 */ -#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) -# define PNG_IO_STATE_SUPPORTED -#endif - -#ifndef PNG_LITERAL_SHARP -# define PNG_LITERAL_SHARP 0x23 -#endif -#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET -# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b -#endif -#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET -# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d -#endif -#ifndef PNG_STRING_NEWLINE -#define PNG_STRING_NEWLINE "\n" -#endif - -/* These are currently experimental features, define them if you want */ - -/* Very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# define PNG_USE_READ_MACROS -#endif - -/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ - -#if !defined(PNG_NO_POINTER_INDEXING) && \ - !defined(PNG_POINTER_INDEXING_SUPPORTED) -# define PNG_POINTER_INDEXING_SUPPORTED -#endif - - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.4.0. - */ - -/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif - -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_USER_CHUNKS -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -# ifndef PNG_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_NO_CONVERT_tIME -# ifndef _WIN32_WCE -/* The "tm" structure is not supported on WindowsCE */ -# ifndef PNG_CONVERT_tIME_SUPPORTED -# define PNG_CONVERT_tIME_SUPPORTED -# endif -# endif -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_WRITE_FILTER -# ifndef PNG_WRITE_FILTER_SUPPORTED -# define PNG_WRITE_FILTER_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* Need the time information for converting tIME chunks */ -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on WindowsCE */ -# include -#endif - /* Some typedefs to get us started. These should be safe on most of the * common platforms. The typedefs should be at least as large as the * numbers suggest (a png_uint_32 must be at least 32 bits long), but they @@ -1095,11 +502,11 @@ typedef short png_int_16; typedef unsigned char png_byte; #ifdef PNG_NO_SIZE_T - typedef unsigned int png_size_t; +typedef unsigned int png_size_t; #else - typedef size_t png_size_t; +typedef size_t png_size_t; #endif -#define png_sizeof(x) sizeof(x) +#define png_sizeof(x) (sizeof (x)) /* The following is needed for medium model support. It cannot be in the * pngpriv.h header. Needs modification for other compilers besides @@ -1119,20 +526,20 @@ typedef unsigned char png_byte; # else # define LDATA 0 # endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ # if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K +# define PNG_MAX_MALLOC_64K /* only used in build */ # if (LDATA != 1) # ifndef FAR # define FAR __far # endif # define USE_FAR_KEYWORD # endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ # endif /* __WIN32__, __FLAT__, __CYGWIN__ */ #endif /* __BORLANDC__ */ @@ -1162,26 +569,37 @@ typedef unsigned char png_byte; #endif /* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ + * to fixed-point with a multiple of 100,000, e.g., gamma + */ typedef png_int_32 png_fixed_point; /* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; -#ifndef PNG_NO_STDIO -typedef FILE * png_FILE_p; +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; #endif #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_doublep; #endif /* Pointers to pointers; i.e. arrays */ @@ -1200,269 +618,6 @@ typedef double FAR * FAR * png_doublepp; /* Pointers to pointers to pointers; i.e., pointer to array */ typedef char FAR * FAR * FAR * png_charppp; -/* Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif - -#ifdef __CYGWIN__ -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# ifndef PNG_IMPEXP - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# ifndef PNG_IMPEXP -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef PNG_BUILDSYMS -# ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END -# endif -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. - */ -# ifdef __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_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# 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 \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif /* PNG_PRIVATE */ -# endif /* __GNUC__ */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#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 - -/* Users may want to use these so they are not private. Any library - * functions that are passed far data must be model-independent. - */ - -/* memory model/platform independent fns */ -#ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif -#endif - -#ifdef USE_FAR_KEYWORD -/* Use this to make far-to-near assignments */ -# define CHECK 1 -# 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 -# 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) sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -# endif -# endif -#endif - /* png_alloc_size_t is guaranteed to be no smaller than png_size_t, * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 * to png_alloc_size_t are not necessary; in fact, it is recommended @@ -1473,38 +628,22 @@ typedef char FAR * FAR * FAR * png_charppp; * to encounter practical situations that require such conversions. */ #if defined(__TURBOC__) && !defined(__FLAT__) -# define png_mem_alloc farmalloc -# define png_mem_free farfree typedef unsigned long png_alloc_size_t; #else # if defined(_MSC_VER) && defined(MAXSEG_64K) -# define png_mem_alloc(s) halloc(s, 1) -# define png_mem_free hfree typedef unsigned long png_alloc_size_t; # else -# if defined(_WINDOWS_) && (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) -# define png_mem_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) -# define png_mem_free(p) HeapFree(GetProcessHeap(), 0, p) - typedef DWORD png_alloc_size_t; + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; # else -# define png_mem_alloc malloc -# define png_mem_free free typedef png_size_t png_alloc_size_t; # endif # endif #endif -/* End of memory model/platform independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - - -/* Added at libpng-1.2.8 */ -#endif /* PNG_VERSION_INFO_ONLY */ #endif /* PNGCONF_H */ diff --git a/extern/libpng/include/pngdebug.h b/extern/libpng/include/pngdebug.h new file mode 100644 index 0000000000..16f81fdd14 --- /dev/null +++ b/extern/libpng/include/pngdebug.h @@ -0,0 +1,157 @@ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' tab characters (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +# endif +# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +# endif +# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +# endif +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# if (PNG_DEBUG > 1) +# ifndef _DEBUG +# define _DEBUG +# endif +# ifndef png_debug +# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +# endif +# endif +# else /* PNG_DEBUG_FILE || !_MSC_VER */ +# ifndef PNG_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# ifndef PNG_DEBUG_FILE +# define PNG_DEBUG_FILE stderr +# endif /* PNG_DEBUG_FILE */ + +# if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } while (0) +# endif +# endif /* __STDC __ */ +# endif /* (PNG_DEBUG > 1) */ + +# endif /* _MSC_VER */ +# endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +# define png_debug(l, m) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/extern/libpng/include/pngerror.c b/extern/libpng/include/pngerror.c new file mode 100644 index 0000000000..8290bb4106 --- /dev/null +++ b/extern/libpng/include/pngerror.c @@ -0,0 +1,447 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr, + png_const_charp error_message)),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +PNG_FUNCTION(void,PNGAPI +png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +PNG_FUNCTION(void,PNGAPI +png_err,(png_structp png_ptr),PNG_NORETURN) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* 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'); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +#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, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); + buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_ERROR_TEXT_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_FUNCTION(void, +png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + png_memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + return NULL; + + png_ptr->longjmp_fn = longjmp_fn; + return &png_ptr->png_jmpbuf; +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#endif +#ifndef PNG_CONSOLE_IO_SUPPORTED + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn) + { +# 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); + } + +# else + png_ptr->longjmp_fn(png_ptr->png_jmpbuf, val); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(png_ptr) /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* 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) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | + PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngget.c b/extern/libpng/include/pngget.c new file mode 100644 index 0000000000..b5e5798c02 --- /dev/null +++ b/extern/libpng/include/pngget.c @@ -0,0 +1,1032 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->y_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && + info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit != 0) + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, + png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +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) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +png_const_bytep PNGAPI +png_get_signature(png_const_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +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) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + if (white_x != NULL) + *white_x = info_ptr->x_white; + if (white_y != NULL) + *white_y = info_ptr->y_white; + if (red_x != NULL) + *red_x = info_ptr->x_red; + if (red_y != NULL) + *red_y = info_ptr->y_red; + if (green_x != NULL) + *green_x = info_ptr->x_green; + if (green_y != NULL) + *green_y = info_ptr->y_green; + if (blue_x != NULL) + *blue_x = info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +png_uint_32 PNGFAPI +png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + *file_gamma = info_ptr->gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma) +{ + png_fixed_point igamma; + png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma); + + if (ok) + *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA"); + + return ok; +} + +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr, + int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + + return (0); +} +#endif + +png_uint_32 PNGAPI +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, int *interlace_type, int *compression_type, + int *filter_type) + +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(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, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING_ARITHMETIC */ +# endif /* FIXED_POINT */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + + return(0); +} +#endif /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + + return (retval); +} +#endif /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +png_uint_32 PNGAPI +png_get_text(png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" : + (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + + if (num_text != NULL) + *num_text = 0; + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return info_ptr->unknown_chunks_num; + } + + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_const_structp png_ptr) +{ + return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->zbuf_size : 0L); +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_structp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structp png_ptr) +{ + return ((png_ptr->chunk_name[0] << 24) + + (png_ptr->chunk_name[1] << 16) + + (png_ptr->chunk_name[2] << 8) + + (png_ptr->chunk_name[3])); +} + +png_const_bytep PNGAPI +png_get_io_chunk_name (png_structp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pnginfo.h b/extern/libpng/include/pnginfo.h new file mode 100644 index 0000000000..fa19f85e72 --- /dev/null +++ b/extern/libpng/include/pnginfo.h @@ -0,0 +1,270 @@ + +/* pnginfo.h - header file for PNG reference library + * + * 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, using png_set_*() functions, then + * call png_write_info(). + * + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. In libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + png_fixed_point gamma; +#endif + +#ifdef PNG_sRGB_SUPPORTED + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * 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 + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ + png_fixed_point x_white; + png_fixed_point y_white; + png_fixed_point x_red; + png_fixed_point y_red; + png_fixed_point x_green; + png_fixed_point y_green; + png_fixed_point x_blue; + png_fixed_point y_blue; +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + int unknown_chunks_num; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) + non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/extern/libpng/include/pngmem.c b/extern/libpng/include/pngmem.c new file mode 100644 index 0000000000..a15d8b0859 --- /dev/null +++ b/extern/libpng/include/pngmem.c @@ -0,0 +1,658 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (png_get_copyright(NULL)); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + + else +# endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } + +# endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + + else +# endif + + if (size != (size_t)size) + ret = NULL; + + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if (png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + + else + num_blocks = 1; + + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +# 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", "M" */ + + else + png_warning(png_ptr, "Out Of Memory"); +# endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +# endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +# 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", "m" */ + + else + png_warning(png_ptr, "Out Of memory"); +# endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +# 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" */ + + else + png_warning(png_ptr, "Out of Memory"); +# endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + + else + ret = farmalloc(size); + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */ + + else + png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */ + } +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + farfree(ptr); +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); + } +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +# endif + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +# endif /* PNG_USER_MEM_SUPPORTED */ +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); + +# else + free(struct_ptr); + +# endif +# endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + + else +# endif + return NULL; + } +# endif + + /* Check for overflow */ +# if defined(__TURBOC__) && !defined(__FLAT__) + + if (size != (unsigned long)size) + ret = NULL; + + else + ret = farmalloc(size); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + + else + ret = halloc(size, 1); + +# else + if (size != (size_t)size) + ret = NULL; + + else + ret = malloc((size_t)size); +# endif +# endif + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); + +# else + free(ptr); + +# endif +# endif +} +#endif /* Not Borland DOS special memory handler */ + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} + + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngpread.c b/extern/libpng/include/pngpread.c new file mode 100644 index 0000000000..5ab9007a16 --- /dev/null +++ b/extern/libpng/include/pngpread.c @@ -0,0 +1,1854 @@ + +/* pngpread.c - read a png file in push mode + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGCBAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ + PNG_IDAT; + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has someplace to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream (a stream with a missing end code) can still + * be handled, otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and therefore + * change the current behavior (see comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5). + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place tEXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place zTXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep)text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place iTXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_size_t)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +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) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/extern/libpng/include/pngpriv.h b/extern/libpng/include/pngpriv.h new file mode 100644 index 0000000000..a7e3b52727 --- /dev/null +++ b/extern/libpng/include/pngpriv.h @@ -0,0 +1,1246 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * 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.) + * + * Last changed in libpng 1.5.2 [March 31, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* This is required for the definition of abort(), used as a last ditch + * error handler when all else fails. + */ +#include + +#define PNGLIB_BUILD +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif +#include "png.h" +#include "pnginfo.h" +#include "pngstruct.h" + +/* This is used for 16 bit gamma tables - only the top level pointers are const, + * this could be changed: + */ +typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + +/* Added at libpng-1.2.9 */ +/* Moved to pngpriv.h at libpng-1.5.0 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. We may need it here to get the correct configuration on things + * like limits. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# 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; +#endif + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* If warnings or errors are turned off the code is disabled + * or redirected here. + */ +#ifndef PNG_WARNINGS_SUPPORTED +# define png_warning(s1,s2) ((void)0) +# define png_chunk_warning(s1,s2) ((void)0) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +#ifndef PNG_EXTERN +/* The functions exported by PNG_EXTERN are internal functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it + * is possible to have run-time registry of chunk-handling functions, + * some of these might be made available again. +# define PNG_EXTERN extern + */ +# define PNG_EXTERN +#endif + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include + +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +#endif + +/* Moved here around 1.5.0beta36 from pngconf.h */ +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* Memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# 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 + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#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_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#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_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 + /* 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_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximuum for png_size_t. The value can be overriden in a library build + * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably + * lower value (e.g. 255 works). A lower value may help memory usage (slightly) + * and may even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#else +PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, + png_const_charp text)); +#endif +#endif + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro wherever it's + * needed. + */ +#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} +#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#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'} + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), + PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2, + PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)), + PNG_ALLOCATED); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items, + uInt size)),PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr)); +# endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Read and check the PNG file signature */ +PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +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) +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)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, + png_const_bytep ptr, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, + png_const_colorp palette, png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +# endif +# ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +# endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, + png_const_color_8p sbit, int color_type)); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_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)); +# endif +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_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_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_const_charp name, int compression_type, + png_const_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_const_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_const_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, + png_const_uint_16p hist, int num_hist)); +#endif + +#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, + png_const_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text)); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_const_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_const_charp width, png_const_charp height)); +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_const_bytep prev_row, + int filter)); + +/* Choose the best filter to use and filter the row data */ +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)); +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info, + png_bytep row, int at_start)); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep palette_lookup, + png_const_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +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 +#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)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans, + int num_trans)); +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. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_const_bytep chunk_name)); + +/* Handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +# ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_CHECK_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_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_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +/* Currently only used by png_check_cHRM_fixed */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif + +/* Added at libpng version 1.4.0 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr, png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_READ_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumpitions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, + png_size_t size, double fp, unsigned int precision)); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp)); +#endif /* FIXED_POINT */ +#endif /* READ_sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numb1.ers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#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 */ +#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 */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* 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 + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +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. + */ +PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, + png_size_t size)); +#endif /* pCAL || sCAL */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, + 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 multiplied_by, png_int_32 divided_by)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value, + * there are no warnings. + */ +PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a)); + +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. + */ +PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, + png_fixed_point b)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * 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_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_value)); +PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, + png_fixed_point gamma_value)); +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + int bit_depth)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNGPRIV_H */ diff --git a/extern/libpng/include/pngread.c b/extern/libpng/include/pngread.c new file mode 100644 index 0000000000..aa84001c45 --- /dev/null +++ b/extern/libpng/include/pngread.c @@ -0,0 +1,1473 @@ + +/* pngread.c - read a PNG file + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(png_structp,PNGAPI +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_ALLOCATED) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(png_structp,PNGAPI +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_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + volatile int png_cleanup_needed = 0; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + malloc_fn, mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; + +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + +# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + 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)) +#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)); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + 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; + } + } + + if (!png_cleanup_needed) + { + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); + + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!png_cleanup_needed) + { + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: + break; /* Do nothing */ + + case Z_MEM_ERROR: + png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; + break; + + case Z_STREAM_ERROR: + png_warning(png_ptr, "zlib stream error"); + png_cleanup_needed = 1; + break; + + case Z_VERSION_ERROR: + png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; + break; + + default: png_warning(png_ptr, "Unknown zlib error"); + png_cleanup_needed = 1; + } + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + + return (png_ptr); +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, length); + + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call;" + " row buffer not reallocated"); + + png_read_transform_info(png_ptr, info_ptr); +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_start_read_image() call;" + " row buffer not reallocated"); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +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) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_benign_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, png_pass_dsp_mask[png_ptr->pass]); + + if (row != NULL) + png_combine_row(png_ptr, row, png_pass_mask[png_ptr->pass]); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#ifdef PNG_TEXT_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#ifdef PNG_READ_TEXT_SUPPORTED + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_free(png_ptr, png_ptr->gamma_table); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#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 + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + 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)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- 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. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16 bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(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). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/extern/libpng/include/pngrio.c b/extern/libpng/include/pngrio.c new file mode 100644 index 0000000000..e9c381c5ba --- /dev/null +++ b/extern/libpng/include/pngrio.c @@ -0,0 +1,176 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.5.0 [January 6, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +# ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +# else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, read, io_ptr); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + + if (err != read) + break; + + else + check += err; + + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +# endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * + * png_ptr - pointer to a png input data structure + * + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/extern/libpng/include/pngrtran.c b/extern/libpng/include/pngrtran.c new file mode 100644 index 0000000000..de5871add0 --- /dev/null +++ b/extern/libpng/include/pngrtran.c @@ -0,0 +1,4303 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + if (png_ptr == NULL) + return; + + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + 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); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_16_TO_8; + png_ptr->transformations &= ~PNG_EXPAND_16; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* 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 + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + + if (t == NULL) + break; + + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#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) +{ + png_debug(1, "in png_set_gamma_fixed"); + + 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; + png_ptr->gamma = file_gamma; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +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")); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#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->transformations &= ~PNG_16_TO_8; + + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + if (png_ptr != NULL) + { + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + if (png_ptr == NULL) + return; + + switch(error_action) + { + case 1: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if (red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + + 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); + } + + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + + 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); + } +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + if (png_ptr == NULL) + return; + + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + { +#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 defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#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. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + 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) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0xff; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x55; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x11; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + default: + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + 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; + +#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; itrans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#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)) + { + int i, k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff) + k=1; /* Partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= ~PNG_GAMMA; + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* Could skip if no transparency */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + png_fixed_point g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + default: + g = PNG_FP_1; /* back_1 */ + gs = PNG_FP_1; /* back */ + break; + } + + if (png_gamma_significant(gs)) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + + 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_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 && + png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + 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. + */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations &= ~PNG_GAMMA; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + png_fixed_point g = PNG_FP_1; + png_fixed_point gs = PNG_FP_1; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = png_ptr->screen_gamma; + /* gs = PNG_FP_1; */ + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + png_error(png_ptr, "invalid background gamma type"); + } + + png_ptr->background_1.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, g); + + png_ptr->background.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, gs); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = png_gamma_correct(png_ptr, + png_ptr->background.red, g); + + png_ptr->background_1.green = png_gamma_correct(png_ptr, + png_ptr->background.green, g); + + png_ptr->background_1.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, g); + + png_ptr->background.red = png_gamma_correct(png_ptr, + png_ptr->background.red, gs); + + png_ptr->background.green = png_gamma_correct(png_ptr, + png_ptr->background.green, gs); + + png_ptr->background.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, gs); + } + + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } + } +#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)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + /* Handled alpha, still need to strip the channel. */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + + if (sg < 0 || sg > 8) + sg = 0; + + if (sb < 0 || sb > 8) + sb = 0; + + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#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 + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + + info_ptr->num_trans = 0; + } + } +#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_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; + info_ptr->background = png_ptr->background; + } +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->transformations & PNG_GAMMA) + { + 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; + } +#endif +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + + 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 + 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 + */ +#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) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + 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 + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + + /* Delay the 'expand 16' step until later for efficiency, so that the + * intermediate steps work with 8 bit data. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (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, because SWAP_ALPHA happens later*/); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + 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_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 + ); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_BACKGROUND_SUPPORTED + !((png_ptr->transformations & PNG_BACKGROUND) && + ((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); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (png_ptr->row_info.rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#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_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /*NOTE: this must be in the wrong place - what happens if BGR is set too? + * Need pngvalid to test this combo. + */ + /* 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, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, + png_const_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + + if ( + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + default: + break; + + case 2: + { + png_bytep bp; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +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; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i> 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: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + 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_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } +#endif + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + + else + { + /* This changes the data from G to XG */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from GG to XXGG */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from RGB to XRGB */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } +#endif + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GG to RRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This changes GA to RGBA */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GGAA to RRGGBBAA */ + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + 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 + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * (THIS LINK IS DEAD June 2008) + * New link: + * + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) + >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= 2; + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_COLOR); + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +/* 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. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + + +#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 +#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 +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + int shift; + + png_debug(1, "in png_do_background"); + + 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) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_color->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + *sp = (png_byte)background->gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + *sp = (png_byte)background->gray; + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == trans_color->gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == trans_color->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + 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) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + 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) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + 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) + { + /* 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); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + 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) + { + *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); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *dp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + 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); + +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 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); + } + +#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); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + 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 + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } + +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + 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); + } +#endif + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 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; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + + else + { + png_composite(*dp, *sp, a, background->red); + + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + 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_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 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); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 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); + } + + else + { + png_uint_16 v, w, x; + + 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); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + 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) + { + *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); + } + + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + 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, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 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); + } + } + } + } + break; + } + + 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 + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * 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_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + default: + break; + } + } +} +#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. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift += 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (trans_alpha != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + + else + *dp-- = trans_alpha[*sp]; + + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray & 0x01) * 0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray & 0x03) * 0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray & 0x0f) * 0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (png_byte)((gray >> 8) & 0xff); + png_byte gray_low = (png_byte)(gray & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + 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); + 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++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + 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); + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#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, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); + *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/extern/libpng/include/pngrutil.c b/extern/libpng/include/pngrutil.c new file mode 100644 index 0000000000..d476431744 --- /dev/null +++ b/extern/libpng/include/pngrutil.c @@ -0,0 +1,3632 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#define png_strtod(p,a,b) strtod(a,b) + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return (uval); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + png_uint_32 uval = + ((png_uint_32)(*(buf )) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + ((png_uint_32)(*(buf + 3)) ) ; + + return uval; +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format and there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000L) == 0) /* non-negative */ + return uval; + + uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */ + return -(png_int_32)uval; +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + /* ANSI-C requires an int value to accomodate at least 16 bits so this + * works and allows the compiler not to worry about possible narrowing + * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * than 16 bits either.) + */ + unsigned int val = + ((unsigned int)(*buf) << 8) + + ((unsigned int)(*(buf + 1))); + + return (png_uint_16)val; +} + +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name. */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %u", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_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) +{ + png_size_t count = 0; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't + * even necessarily handle 65536 bytes) because the type uInt is "16 bits or + * more". Consequently it is necessary to chunk the input to zlib. This + * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value + * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a + * lower value in pngpriv.h and this may sometimes have a performance + * advantage, because it forces access of the input data to be separated from + * at least some of the use by some period of time. + */ + png_ptr->zstream.next_in = data; + /* avail_in is set below from 'size' */ + png_ptr->zstream.avail_in = 0; + + while (1) + { + int ret, avail; + + /* The setting of 'avail_in' used to be outside the loop, by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o + * data to be passed through zlib at the unavoidable cost of requiring a + * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX + * input bytes. + */ + if (png_ptr->zstream.avail_in == 0 && size > 0) + { + if (size <= ZLIB_IO_MAX) + { + /* The value is less than ZLIB_IO_MAX so the cast is safe: */ + png_ptr->zstream.avail_in = (uInt)size; + size = 0; + } + + else + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + size -= ZLIB_IO_MAX; + } + } + + /* Reset the output buffer each time round - we empty it + * after every inflate call. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + + /* First copy/count any new output - but only if we didn't + * get an error code. + */ + if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + { + png_size_t space = avail; /* > 0, see above */ + + if (output != 0 && output_size > count) + { + png_size_t copy = output_size - count; + + if (space < copy) + copy = space; + + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += space; + } + + if (ret == Z_OK) + continue; + + /* Termination conditions - always reset the zstream, it + * must be left in inflateInit state. + */ + png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + + if (ret == Z_STREAM_END) + return count; /* NOTE: may be zero. */ + + /* Now handle the error codes - the API always returns 0 + * and the error message is dumped into the uncompressed + * buffer if available. + */ + { + PNG_CONST char *msg; +#ifdef PNG_CONSOLE_IO_SUPPORTED + char umsg[52]; +#endif + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + + else + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream in %s chunk"; + break; + + case Z_DATA_ERROR: + msg = "Data error in compressed datastream in %s chunk"; + 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 + } + + png_warning(png_ptr, msg); + } + + /* 0 means an error - notice that this code simply ignores + * zero length compressed chunks as a result. + */ + return 0; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + /* The caller should guarantee this */ + if (prefix_size > chunklength) + { + /* The recovery is to delete the chunk. */ + png_warning(png_ptr, "invalid chunklength"); + prefix_size = 0; /* To delete everything */ + } + + else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + png_size_t expanded_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_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. + */ +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#endif + png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + + /* If the size is zero either there was an error and a message + * has already been output (warning) or the size really is zero + * and we have nothing to do - the code will exit through the + * error case below. + */ +#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ + defined(PNG_USER_CHUNK_MALLOC_MAX) + else if (expanded_size > 0) +#else + if (expanded_size > 0) +#endif + { + /* Success (maybe) - really uncompress the chunk. */ + png_size_t new_size = 0; + png_charp text = png_malloc_warn(png_ptr, + prefix_size + expanded_size + 1); + + if (text != NULL) + { + png_memcpy(text, png_ptr->chunkdata, prefix_size); + new_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + (png_bytep)(text + prefix_size), expanded_size); + text[prefix_size + expanded_size] = 0; /* just in case */ + + if (new_size == expanded_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength = prefix_size + expanded_size; + return; /* The success return! */ + } + + png_warning(png_ptr, "png_inflate logic error"); + png_free(png_ptr, text); + } + + else + png_warning(png_ptr, "Not enough memory to decompress chunk"); + } + } + + 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 + + /* The recovery is to simply drop the data. */ + } + + /* Generic error return - leave the prefix, delete the compressed + * data, reallocate the chunkdata to remove the potentially large + * amount of compressed data. + */ + { + png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); + + if (text != NULL) + { + if (prefix_size > 0) + png_memcpy(text, png_ptr->chunkdata, prefix_size); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + + /* This is an extra zero in the 'uncompressed' part. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + } + /* Ignore a malloc error here - it is safe. */ + } + + *newlength = prefix_size; +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + default: /* invalid, png_set_IHDR calls png_error */ + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually need the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + * we have two options: an error abort, or a warning and we + * ignore the data in this chunk (which should be OK, since + * it's considered ancillary for a RGB or RGBA image). + */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_benign_error(png_ptr, "CRC error"); + } + + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + + png_crc_finish(png_ptr, length); + + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = png_get_fixed_point(NULL, buf); + + /* Check for zero gamma or an error. */ + if (igamma <= 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with out of range gamma"); + + return; + } + +# ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + 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 + return; + } + } +# endif /* PNG_READ_sRGB_SUPPORTED */ + +# ifdef PNG_READ_GAMMA_SUPPORTED + /* Gamma correction on read is supported. */ + png_ptr->gamma = igamma; +# endif + /* And set the 'info' structure members. */ + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; + png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, + y_blue; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +# ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +# endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + + if (png_crc_finish(png_ptr, 0)) + return; + + x_white = png_get_fixed_point(NULL, buf); + y_white = png_get_fixed_point(NULL, buf + 4); + x_red = png_get_fixed_point(NULL, buf + 8); + y_red = png_get_fixed_point(NULL, buf + 12); + x_green = png_get_fixed_point(NULL, buf + 16); + y_green = png_get_fixed_point(NULL, buf + 20); + x_blue = png_get_fixed_point(NULL, buf + 24); + y_blue = png_get_fixed_point(NULL, buf + 28); + + if (x_white == PNG_FIXED_ERROR || + y_white == PNG_FIXED_ERROR || + x_red == PNG_FIXED_ERROR || + y_red == PNG_FIXED_ERROR || + x_green == PNG_FIXED_ERROR || + y_green == PNG_FIXED_ERROR || + x_blue == PNG_FIXED_ERROR || + y_blue == PNG_FIXED_ERROR) + { + png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(y_green, 60000L, 1000) || + 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 */ + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + + png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, + x_green, y_green, x_blue, y_blue); +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + 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 + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size; + png_alloc_size_t profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if (profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if (prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC )) << 24) | + ((*(pC + 1)) << 16) | + ((*(pC + 2)) << 8) | + ((*(pC + 3)) ); + + /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, + * because profile_size is a 32 bit value. + */ + if (profile_size < profile_length) + profile_length = profile_size; + + /* And the following guarantees that profile_size == profile_length. */ + if (profile_size > profile_length) + { + 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 + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, + profile_size); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; + png_sPLT_entryp pp; + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + png_uint_32 dl; + png_size_t max_dl; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; + entry_start++) + /* Empty loop to find end of name */ ; + + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length (and use 'length', not 'slength' here for clarity - + * they are guaranteed to be the same, see the tests above.) + */ + data_length = length - (png_uint_32)(entry_start - + (png_bytep)png_ptr->chunkdata); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + + 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); + } + + 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); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + + if (num != (unsigned int)png_ptr->num_palette || num > + (unsigned int)PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + * in order to get the parameter information. + */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + * equation types. + */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + + params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)(nparams * png_sizeof(png_charp))); + + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t slength, i; + int state; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + length + 1); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the unit. */ + if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) + { + png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 0; + state = 0; + + if (png_ptr->chunkdata[1] == 45 /* negative width */ || + !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 + { + png_size_t heighti = i; + + if (png_ptr->chunkdata[i] == 45 /* negative height */ || + !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i != slength) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], + png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); + } + + /* Clean up - just free the temporarily allocated buffer. */ + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for tEXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for zTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_type = *(++text); + + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + + text++; /* Skip the compression_method byte */ + } + + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk"); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for iTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + + text++; /* Skip NUL separator */ + + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk"); +} +#endif + +/* This function is called when we haven't found a handler for a + * chunk. If there isn't a problem with the chunk itself (ie bad + * chunk name, CRC, or a critical chunk), the chunk is silently ignored + * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + * case it will be saved away to be written out later. + */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for unknown chunk"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + PNG_IDAT; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + || (png_ptr->read_user_chunk_fn != NULL) +#endif + ) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#ifndef PNG_READ_USER_CHUNKS_SUPPORTED + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + * This function can't have the "critical chunk check" incorporated + * into it, since in the future we will need to be able to call user + * functions to handle unknown critical chunks after we check that + * the chunk name itself is valid. + */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + * row. This routine takes care of alpha and transparency if requested. + * This routine also handles the two methods of progressive display + * of interlaced images, depending on the mask value. + * The mask value describes which pixels are to be combined with + * the row. The pattern always repeats every 8 pixels, so just 8 + * bits are needed. A one indicates the pixel is to be combined, + * a zero indicates the pixel is to be skipped. This is in addition + * to any alpha or transparency value associated with the pixel. If + * you want all pixels to be combined, pass 0xff (255) in mask. + */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + + case PNG_FILTER_VALUE_SUB: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + png_const_bytep cp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_error(png_ptr, "Ignoring bad adaptive filter type"); + /*NOT REACHED */ + break; + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + PNG_IDAT; + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + + max_pixel_depth = png_ptr->pixel_depth; + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#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)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + + else + max_pixel_depth = 32; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); + +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, + row_bytes + 48); + + png_ptr->old_big_row_buf_size = row_bytes + 48; + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf. + */ + png_ptr->row_buf = png_ptr->big_row_buf + 32 - + (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F); + + png_ptr->old_big_row_buf_size = row_bytes + 48; +#else + /* Use 32 bytes of padding before and 16 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 32; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; + } + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/extern/libpng/include/pngset.c b/extern/libpng/include/pngset.c new file mode 100644 index 0000000000..2cfcf33bdf --- /dev/null +++ b/extern/libpng/include/pngset.c @@ -0,0 +1,1225 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +void PNGFAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +# ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +# endif + { + info_ptr->x_white = white_x; + info_ptr->y_white = white_y; + info_ptr->x_red = red_x; + info_ptr->y_red = red_y; + info_ptr->x_green = green_x; + info_ptr->y_green = green_y; + info_ptr->x_blue = blue_x; + info_ptr->y_blue = blue_y; + info_ptr->valid |= PNG_INFO_cHRM; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +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, double green_y, double blue_x, double blue_y) +{ + png_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + 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. + */ + 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"); + + else + { + info_ptr->gamma = file_gamma; + info_ptr->valid |= PNG_INFO_gAMA; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)); + + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + info_ptr->free_me |= PNG_FREE_HIST; +} +#endif + +void PNGAPI +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, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > + (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = 0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +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, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + /* Validate params[nparams] */ + for (i=0; ipcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + + png_memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + + png_memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * png_sizeof(png_charp))); + + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + + png_memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + 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)) + png_error(png_ptr, "Invalid sCAL width"); + + 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; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw); + + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_width, swidth, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh); + + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_height, sheight, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width, + double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width); + png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_const_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)srgb_intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + +# ifdef PNG_gAMA_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, 45455L); +# endif + +# ifdef PNG_cHRM_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270L, 32900L, + /* red */ 64000L, 33000L, + /* green */ 30000L, 60000L, + /* blue */ 15000L, 6000L + ); +# endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen); + + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types + */ + info_ptr->iccp_compression = (png_byte)compression_type; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", ((png_ptr == NULL || + png_ptr->chunk_name[0] == '\0') ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); + info_ptr->free_me |= PNG_FREE_TEXT; + } + + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_warning(png_ptr, "text compression mode is out of range"); + continue; + } + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +# ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + + else + lang_len = 0; + + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + + else + lang_key_len = 0; + } +# else /* PNG_iTXt_SUPPORTED */ + { + png_warning(png_ptr, "iTXt chunk not supported"); + continue; + } +# endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +# ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + + else +# endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_size_t) + (key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + return(1); + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; + + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + + else + { + textp->lang=NULL; + textp->lang_key=NULL; + textp->text = textp->key + key_len + 1; + } + + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + + *(textp->text + text_length) = '\0'; + +# ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + + else +# endif + { + textp->text_length = text_length; + textp->itxt_length = 0; + } + + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = + (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + + png_memcpy(&(info_ptr->trans_color), trans_color, + png_sizeof(png_color_16)); + + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_const_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_size_t)png_sizeof(png_sPLT_t)); + + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes"); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_const_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; + info_ptr->free_me |= PNG_FREE_SPLT; +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + (png_size_t)info_ptr->unknown_chunks_num * + png_sizeof(png_unknown_chunk)); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_const_unknown_chunkp from = unknowns + i; + + png_memcpy(to->name, from->name, png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)from->size); + + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + to->size = 0; + } + + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; + info_ptr->free_me |= PNG_FREE_UNKN; +} + +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return (png_uint_32)0; + + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + return; + } + + if (chunk_list == NULL) + return; + + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_size_t)(5*(num_chunks + old_num_chunks))); + + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; + png_ptr->free_me |= PNG_FREE_LIST; +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + + info_ptr->row_pointers = row_pointers; + + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_size_t size) +{ + if (png_ptr == NULL) + return; + + png_free(png_ptr, png_ptr->zbuf); + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, "Attempt to set buffer size beyond max ignored"); + png_ptr->zbuf_size = ZLIB_IO_MAX; + size = ZLIB_IO_MAX; /* must fit */ + } + + else + png_ptr->zbuf_size = (uInt)size; + + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + + /* The following ensures a relatively safe failure if this gets called while + * the buffer is actually in use. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.avail_in = 0; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structp png_ptr, + png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + + else + png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngstruct.h b/extern/libpng/include/pngstruct.h new file mode 100644 index 0000000000..8d781faefe --- /dev/null +++ b/extern/libpng/include/pngstruct.h @@ -0,0 +1,308 @@ + +/* pngstruct.h - header file for PNG reference library + * + * 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#include "zlib.h" + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf png_jmpbuf; /* 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 */ + png_error_ptr warning_fn; /* function for printing warnings */ + 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 */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + uInt zbuf_size; /* size of zbuf (typically 65536) */ + 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 */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + 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_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point gamma; /* file gamma value */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* which original index points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk; +#endif + +/* New members added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + png_size_t old_prev_row_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/extern/libpng/include/pngtest.c b/extern/libpng/include/pngtest.c new file mode 100644 index 0000000000..a6a3ae489c --- /dev/null +++ b/extern/libpng/include/pngtest.c @@ -0,0 +1,1787 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.5.0 [January 6, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#include "zlib.h" +#include "png.h" +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +# include +# include +# include +# define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* The code uses memcmp and memcpy on large objects (typically row pointers) so + * it is necessary to do soemthing special on certain architectures, note that + * the actual support for this was effectively removed in 1.4, so only the + * memory remains in this program: + */ +#define CVT_PTR(ptr) (ptr) +#define CVT_PTR_NOCHECK(ptr) (ptr) +#define png_memcmp memcmp +#define png_memcpy memcpy +#define png_memset memset + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + + fprintf(stdout, "r"); +} + +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + + fprintf(stdout, "w"); +} + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL) + return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, 1, io_ptr); + png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Read Error"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(png_ptr) /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void PNGCBAPI +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + char *test; + test = png_get_error_ptr(png_ptr); + + if (test == NULL) + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + + else + fprintf(STDERR, "%s: libpng warning: %s\n", test, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void PNGCBAPI +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} +#endif /* !PNG_STDIO_SUPPORTED */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + png_sizeof(*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void PNGCBAPI +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %p\n", ptr); + + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +/* Demonstration of user chunk support of the sTER and vpAg chunks */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static png_uint_32 user_chunk_data[4]; + + /* 0: sTER mode + 1 + * 1: vpAg width + * 2: vpAg height + * 3: vpAg units + */ + +static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + png_uint_32 + *my_user_chunk_data; + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + my_user_chunk_data[0]=chunk->data[0]+1; + return (1); + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + + my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + + return (1); + +} +#endif +/* END of code to demonstrate user chunk support */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + + char inbuf[256], outbuf[256]; + + row_buf = NULL; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + user_chunk_data[0] = 0; + user_chunk_data[1] = 0; + user_chunk_data[2] = 0; + user_chunk_data[3] = 0; + png_set_read_user_chunk_fn(read_ptr, user_chunk_data, + read_user_chunk_callback); + +#endif +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(png_jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr), png_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)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } + +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr), png_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + + for (i = 0; i<256; i++) + filters_used[i] = 0; + + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + NULL, 0); +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_bytep profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + * pointed to by png_convert_to_rfc1123() gets free'ed before + * we use it. + */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_bytep trans_alpha; + int num_trans; + png_color_16p trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color)) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_info_ptr are wrong because we + * haven't written anything yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + +/* If we wanted, we could write info in two steps: + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (user_chunk_data[0] != 0) + { + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + unsigned char + ster_chunk_data[1]; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %lu\n", + (unsigned long)(user_chunk_data[0] - 1)); + + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); + png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); + } + + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) + { + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + unsigned char + vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", + (unsigned long)user_chunk_data[1], + (unsigned long)user_chunk_data[2], + (unsigned long)user_chunk_data[3]); + + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); + vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); + } + +#endif +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); + +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong because we + * haven't written the end_info yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + pngtest_debug("Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + pngtest_debug("destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + pngtest_debug("Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + num_in = fread(inbuf, 1, 1, fpin); + num_out = fread(outbuf, 1, 1, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_5_2 Your_png_h_is_not_version_1_5_2; diff --git a/extern/libpng/include/pngtrans.c b/extern/libpng/include/pngtrans.c new file mode 100644 index 0000000000..cf7622cdc6 --- /dev/null +++ b/extern/libpng/include/pngtrans.c @@ -0,0 +1,674 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_const_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_uint_16)filler; + + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA?) */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if (row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* 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_channel(png_row_infop row_info, png_bytep row, int at_start) +{ + 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. + */ + /* GA, GX, XG cases */ + if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 2, ++dp; + + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 8; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) + sp += 2; + else + sp += 4, dp += 2; + + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; + } + + else + return; /* bad bit depth */ + + row_info->channels = 1; + + /* 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; + } + + /* 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; + + /* 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 = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) + sp += 2; + else + 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->pixel_depth = 48; + } + + 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 + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } +#endif + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->user_transform_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 */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structp png_ptr) +{ + if (png_ptr != NULL) + 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/extern/libpng/include/pngvalid.c b/extern/libpng/include/pngvalid.c new file mode 100644 index 0000000000..54c55dd4b6 --- /dev/null +++ b/extern/libpng/include/pngvalid.c @@ -0,0 +1,6709 @@ + +/* pngvalid.c - validate libpng by constructing then reading png files. + * + * Last changed in libpng 1.5.2 [March 31, 2011] + * Copyright (c) 2011 Glenn Randers-Pehrson + * Written by John Cunningham Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * NOTES: + * This is a C program that is intended to be linked against libpng. It + * generates bitmaps internally, stores them as PNG files (using the + * sequential write code) then reads them back (using the sequential + * read code) and validates that the result has the correct data. + * + * The program can be modified and extended to test the correctness of + * transformations performed by libpng. + */ + +#include "png.h" +#if PNG_LIBPNG_VER < 10500 +/* This delibarately lacks the PNG_CONST. */ +typedef png_byte *png_const_bytep; + +/* This is copied from 1.5.1 png.h: */ +#define PNG_INTERLACE_ADAM7_PASSES 7 +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +/* These are needed too for the defualt build: */ +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#endif + +#include "zlib.h" /* For crc32 */ + +#include /* For floating point constants */ +#include /* For malloc */ +#include /* For memcpy, memset */ +#include /* For floor */ + +/* Unused formal parameter errors are removed using the following macro which is + * expected to have no bad effects on performance. + */ +#ifndef UNUSED +# if defined(__GNUC__) || defined(_MSC_VER) +# define UNUSED(param) (void)param; +# else +# define UNUSED(param) +# endif +#endif + +/***************************** EXCEPTION HANDLING *****************************/ +#include "contrib/visupng/cexcept.h" +struct png_store; +define_exception_type(struct png_store*); + +/* The following are macros to reduce typing everywhere where the well known + * name 'the_exception_context' must be defined. + */ +#define anon_context(ps) struct exception_context *the_exception_context = \ + &(ps)->exception_context +#define context(ps,fault) anon_context(ps); png_store *fault + +/******************************* UTILITIES ************************************/ +/* Error handling is particularly problematic in production code - error + * handlers often themselves have bugs which lead to programs that detect + * minor errors crashing. The following functions deal with one very + * common class of errors in error handlers - attempting to format error or + * warning messages into buffers that are too small. + */ +static size_t safecat(char *buffer, size_t bufsize, size_t pos, + PNG_CONST char *cat) +{ + while (pos < bufsize && cat != NULL && *cat != 0) + buffer[pos++] = *cat++; + + if (pos >= bufsize) + pos = bufsize-1; + + buffer[pos] = 0; + return pos; +} + +static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) +{ + char number[64]; + sprintf(number, "%d", n); + return safecat(buffer, bufsize, pos, number); +} + +static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, + int precision) +{ + char number[64]; + sprintf(number, "%.*f", precision, d); + return safecat(buffer, bufsize, pos, number); +} + +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) +{ + switch (bit_depth) + { + case 1: + return 0; + + case 2: + return 1; + + case 4: + return 2; + + case 8: + return 3; + + case 16: + return 4; + + default: + return 7; + } +} + +/* 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. + */ +#define FILEID(col, depth, interlace, width, height, do_interlace) \ + ((png_uint_32)((col) + ((depth)<<3) + ((interlace)<<8) + \ + (((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 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) + +/* 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) +{ + pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); + pos = safecat(buffer, bufsize, pos, " "); + pos = safecat(buffer, bufsize, pos, bit_depths[log_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)"); + if (w > 0 || h > 0) + { + pos = safecat(buffer, bufsize, pos, " "); + pos = safecatn(buffer, bufsize, pos, w); + pos = safecat(buffer, bufsize, pos, "x"); + pos = safecatn(buffer, bufsize, pos, h); + } + + return pos; +} + +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), + WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); +} + +/* Convenience API and defines to list valid formats. Note that 16 bit read and + * write support is required to do 16 bit read tests (we must be able to make a + * 16 bit image to test!) + */ +#ifdef PNG_WRITE_16BIT_SUPPORTED +# define WRITE_BDHI 4 +# ifdef PNG_READ_16BIT_SUPPORTED +# define READ_BDHI 4 +# define DO_16BIT +# endif +#else +# define WRITE_BDHI 3 +#endif +#ifndef DO_16BIT +# define READ_BDHI 3 +#endif + +static int +next_format(png_bytep colour_type, png_bytep bit_depth) +{ + if (*bit_depth == 0) + { + *colour_type = 0, *bit_depth = 1; + return 1; + } + + *bit_depth = (png_byte)(*bit_depth << 1); + + /* Palette images are restricted to 8 bit depth */ + if (*bit_depth <= 8 +# ifdef DO_16BIT + || (*colour_type != 3 && *bit_depth <= 16) +# endif + ) + return 1; + + /* Move to the next color type, or return 0 at the end. */ + switch (*colour_type) + { + case 0: + *colour_type = 2; + *bit_depth = 8; + return 1; + + case 2: + *colour_type = 3; + *bit_depth = 1; + return 1; + + case 3: + *colour_type = 4; + *bit_depth = 8; + return 1; + + case 4: + *colour_type = 6; + *bit_depth = 8; + return 1; + + default: + return 0; + } +} + +static unsigned int +sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, + png_uint_32 x, unsigned int sample_index) +{ + png_uint_32 bit_index, result; + + /* Find a sample index for the desired sample: */ + x *= bit_depth; + bit_index = x; + + if ((colour_type & 1) == 0) /* !palette */ + { + if (colour_type & 2) + bit_index *= 3; + + if (colour_type & 4) + bit_index += x; /* Alpha channel */ + + if (colour_type & (2+4)) + bit_index += sample_index * bit_depth; /* Multiple channels: select one */ + } + + /* Return the sample from the row as an integer. */ + row += bit_index >> 3; + result = *row; + + if (bit_depth == 8) + return result; + + else if (bit_depth > 8) + return (result << 8) + *++row; + + /* Less than 8 bits per sample. */ + bit_index &= 7; + return (result >> (8-bit_index-bit_depth)) & ((1U<> 3] & ~destMask; + unsigned int sourceByte = fromBuffer[fromIndex >> 3]; + + /* Don't rely on << or >> supporting '0' here, just in case: */ + fromIndex &= 7; + if (fromIndex > 0) sourceByte <<= fromIndex; + if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7; + + toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask)); + } + else /* One or more bytes */ + memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3); +} + +/* Compare pixels - they are assumed to start at the first byte in the + * given buffers. + */ +static int +pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width) +{ + if (memcmp(pa, pb, bit_width>>3) == 0) + { + png_uint_32 p; + + if ((bit_width & 7) == 0) return 0; + + /* Ok, any differences? */ + p = pa[bit_width >> 3]; + p ^= pb[bit_width >> 3]; + + if (p == 0) return 0; + + /* There are, but they may not be significant, remove the bits + * after the end (the low order bits in PNG.) + */ + bit_width &= 7; + p >>= 8-bit_width; + + if (p == 0) return 0; + } + + return 1; /* Different */ +} + +/*************************** BASIC PNG FILE WRITING ***************************/ +/* A png_store takes data from the sequential writer or provides data + * to the sequential reader. It can also store the result of a PNG + * write for later retrieval. + */ +#define STORE_BUFFER_SIZE 500 /* arbitrary */ +typedef struct png_store_buffer +{ + struct png_store_buffer* prev; /* NOTE: stored in reverse order */ + png_byte buffer[STORE_BUFFER_SIZE]; +} png_store_buffer; + +#define FILE_NAME_SIZE 64 + +typedef struct png_store_file +{ + struct png_store_file* next; /* as many as you like... */ + char name[FILE_NAME_SIZE]; + 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 */ +} png_store_file; + +/* The following is a pool of memory allocated by a single libpng read or write + * operation. + */ +typedef struct store_pool +{ + struct png_store *store; /* Back pointer */ + struct store_memory *list; /* List of allocated memory */ + png_byte mark[4]; /* Before and after data */ + + /* Statistics for this run. */ + png_alloc_size_t max; /* Maximum single allocation */ + png_alloc_size_t current; /* Current allocation */ + png_alloc_size_t limit; /* Highest current allocation */ + png_alloc_size_t total; /* Total allocation */ + + /* Overall statistics (retained across successive runs). */ + png_alloc_size_t max_max; + png_alloc_size_t max_limit; + png_alloc_size_t max_total; +} store_pool; + +typedef struct png_store +{ + /* For cexcept.h exception handling - simply store one of these; + * the context is a self pointer but it may point to a different + * png_store (in fact it never does in this program.) + */ + struct exception_context + exception_context; + + unsigned int verbose :1; + unsigned int treat_warnings_as_errors :1; + unsigned int expect_error :1; + unsigned int expect_warning :1; + unsigned int saw_warning :1; + unsigned int speed :1; + unsigned int progressive :1; /* use progressive read */ + unsigned int validated :1; /* used as a temporary flag */ + int nerrors; + int nwarnings; + char test[128]; /* Name of test */ + char error[256]; + + /* Read fields */ + png_structp pread; /* Used to read a saved file */ + png_infop piread; + png_store_file* current; /* Set when reading */ + 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 */ + store_pool read_memory_pool; + + /* Write fields */ + png_store_file* saved; + png_structp pwrite; /* Used when writing a new file */ + png_infop piwrite; + png_size_t writepos; /* Position in .new */ + char wname[FILE_NAME_SIZE]; + png_store_buffer new; /* The end of the new PNG file being written. */ + store_pool write_memory_pool; +} png_store; + +/* Initialization and cleanup */ +static void +store_pool_mark(png_byte *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; + + /* 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; + } +} + +/* Use this for random 32 bit values, this function makes sure the result is + * non-zero. + */ +static png_uint_32 +random_32(void) +{ + + for(;;) + { + png_byte mark[4]; + png_uint_32 result; + + store_pool_mark(mark); + result = png_get_uint_32(mark); + + if (result != 0) + return result; + } +} + +static void +store_pool_init(png_store *ps, store_pool *pool) +{ + memset(pool, 0, sizeof *pool); + + pool->store = ps; + pool->list = NULL; + pool->max = pool->current = pool->limit = pool->total = 0; + pool->max_max = pool->max_limit = pool->max_total = 0; + store_pool_mark(pool->mark); +} + +static void +store_init(png_store* ps) +{ + memset(ps, 0, sizeof *ps); + init_exception_context(&ps->exception_context); + store_pool_init(ps, &ps->read_memory_pool); + store_pool_init(ps, &ps->write_memory_pool); + ps->verbose = 0; + ps->treat_warnings_as_errors = 0; + ps->expect_error = 0; + ps->expect_warning = 0; + ps->saw_warning = 0; + ps->speed = 0; + ps->progressive = 0; + ps->validated = 0; + ps->nerrors = ps->nwarnings = 0; + ps->pread = NULL; + ps->piread = NULL; + ps->saved = ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->image = NULL; + ps->cb_image = 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); +} + +static void +store_freebuffer(png_store_buffer* psb) +{ + if (psb->prev) + { + store_freebuffer(psb->prev); + free(psb->prev); + psb->prev = NULL; + } +} + +static void +store_freenew(png_store *ps) +{ + store_freebuffer(&ps->new); + ps->writepos = 0; +} + +static void +store_storenew(png_store *ps) +{ + png_store_buffer *pb; + + if (ps->writepos != STORE_BUFFER_SIZE) + png_error(ps->pwrite, "invalid store call"); + + pb = malloc(sizeof *pb); + + if (pb == NULL) + png_error(ps->pwrite, "store new: OOM"); + + *pb = ps->new; + ps->new.prev = pb; + ps->writepos = 0; +} + +static void +store_freefile(png_store_file **ppf) +{ + if (*ppf != NULL) + { + store_freefile(&(*ppf)->next); + + store_freebuffer(&(*ppf)->data); + (*ppf)->datacount = 0; + free(*ppf); + *ppf = NULL; + } +} + +/* Main interface to file storeage, after writing a new PNG file (see the API + * below) call store_storefile to store the result with the given name and id. + */ +static void +store_storefile(png_store *ps, png_uint_32 id) +{ + png_store_file *pf = malloc(sizeof *pf); + if (pf == NULL) + png_error(ps->pwrite, "storefile: OOM"); + safecat(pf->name, sizeof pf->name, 0, ps->wname); + pf->id = id; + pf->data = ps->new; + pf->datacount = ps->writepos; + ps->new.prev = NULL; + ps->writepos = 0; + + /* And save it. */ + pf->next = ps->saved; + ps->saved = pf; +} + +/* Generate an error message (in the given buffer) */ +static size_t +store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize, + size_t pos, PNG_CONST char *msg) +{ + if (pp != NULL && pp == ps->pread) + { + /* Reading a file */ + pos = safecat(buffer, bufsize, pos, "read: "); + + if (ps->current != NULL) + { + pos = safecat(buffer, bufsize, pos, ps->current->name); + pos = safecat(buffer, bufsize, pos, sep); + } + } + + else if (pp != NULL && pp == ps->pwrite) + { + /* Writing a file */ + pos = safecat(buffer, bufsize, pos, "write: "); + pos = safecat(buffer, bufsize, pos, ps->wname); + pos = safecat(buffer, bufsize, pos, sep); + } + + else + { + /* Neither reading nor writing (or a memory error in struct delete) */ + pos = safecat(buffer, bufsize, pos, "pngvalid: "); + } + + if (ps->test[0] != 0) + { + pos = safecat(buffer, bufsize, pos, ps->test); + pos = safecat(buffer, bufsize, pos, sep); + } + pos = safecat(buffer, bufsize, pos, msg); + return pos; +} + +/* 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) +{ + /* The warning is copied to the error buffer if there are no errors and it is + * the first warning. The error is copied to the error buffer if it is the + * first error (overwriting any prior warnings). + */ + if (is_error ? (ps->nerrors)++ == 0 : + (ps->nwarnings)++ == 0 && ps->nerrors == 0) + 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); + } +} + +/* Functions to use as PNG callbacks. */ +static void +store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */ +{ + png_store *ps = png_get_error_ptr(pp); + + if (!ps->expect_error) + store_log(ps, pp, message, 1 /* error */); + + /* And finally throw an exception. */ + { + struct exception_context *the_exception_context = &ps->exception_context; + Throw ps; + } +} + +static void +store_warning(png_structp pp, png_const_charp message) +{ + png_store *ps = png_get_error_ptr(pp); + + if (!ps->expect_warning) + store_log(ps, pp, message, 0 /* warning */); + else + ps->saw_warning = 1; +} + +static void +store_write(png_structp pp, png_bytep pb, png_size_t st) +{ + png_store *ps = png_get_io_ptr(pp); + + if (ps->pwrite != pp) + png_error(pp, "store state damaged"); + + while (st > 0) + { + size_t cb; + + if (ps->writepos >= STORE_BUFFER_SIZE) + store_storenew(ps); + + cb = st; + + if (cb > STORE_BUFFER_SIZE - ps->writepos) + cb = STORE_BUFFER_SIZE - ps->writepos; + + memcpy(ps->new.buffer + ps->writepos, pb, cb); + pb += cb; + st -= cb; + ps->writepos += cb; + } +} + +static void +store_flush(png_structp pp) +{ + UNUSED(pp) /*DOES NOTHING*/ +} + +static size_t +store_read_buffer_size(png_store *ps) +{ + /* Return the bytes available for read in the current buffer. */ + if (ps->next != &ps->current->data) + return STORE_BUFFER_SIZE; + + return ps->current->datacount; +} + +/* Return total bytes available for read. */ +static size_t +store_read_buffer_avail(png_store *ps) +{ + if (ps->current != NULL && ps->next != NULL) + { + png_store_buffer *next = &ps->current->data; + size_t cbAvail = ps->current->datacount; + + while (next != ps->next && next != NULL) + { + next = next->prev; + cbAvail += STORE_BUFFER_SIZE; + } + + if (next != ps->next) + png_error(ps->pread, "buffer read error"); + + if (cbAvail > ps->readpos) + return cbAvail - ps->readpos; + } + + return 0; +} + +static int +store_read_buffer_next(png_store *ps) +{ + png_store_buffer *pbOld = ps->next; + png_store_buffer *pbNew = &ps->current->data; + if (pbOld != pbNew) + { + while (pbNew != NULL && pbNew->prev != pbOld) + pbNew = pbNew->prev; + + if (pbNew != NULL) + { + ps->next = pbNew; + ps->readpos = 0; + return 1; + } + + png_error(ps->pread, "buffer lost"); + } + + return 0; /* EOF or error */ +} + +/* Need separate implementation and callback to allow use of the same code + * during progressive read, where the io_ptr is set internally by libpng. + */ +static void +store_read_imp(png_store *ps, png_bytep pb, png_size_t st) +{ + if (ps->current == NULL || ps->next == NULL) + png_error(ps->pread, "store state damaged"); + + while (st > 0) + { + size_t cbAvail = store_read_buffer_size(ps) - ps->readpos; + + if (cbAvail > 0) + { + if (cbAvail > st) cbAvail = st; + memcpy(pb, ps->next->buffer + ps->readpos, cbAvail); + st -= cbAvail; + pb += cbAvail; + ps->readpos += cbAvail; + } + + else if (!store_read_buffer_next(ps)) + png_error(ps->pread, "read beyond end of file"); + } +} + +static void +store_read(png_structp pp, png_bytep pb, png_size_t st) +{ + png_store *ps = png_get_io_ptr(pp); + + if (ps == NULL || ps->pread != pp) + png_error(pp, "bad store read call"); + + store_read_imp(ps, pb, st); +} + +static void +store_progressive_read(png_store *ps, png_structp pp, png_infop pi) +{ + /* Notice that a call to store_read will cause this function to fail because + * readpos will be set. + */ + if (ps->pread != pp || ps->current == NULL || ps->next == NULL) + png_error(pp, "store state damaged (progressive)"); + + do + { + if (ps->readpos != 0) + png_error(pp, "store_read called during progressive read"); + + png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps)); + } + while (store_read_buffer_next(ps)); +} + +/***************************** 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 + * allocated memory is followed by a second copy of the 'mark'. + */ +typedef struct store_memory +{ + store_pool *pool; /* Originating pool */ + struct store_memory *next; /* Singly linked list */ + png_alloc_size_t size; /* Size of memory allocated */ + png_byte mark[4]; /* ID marker */ +} store_memory; + +/* Handle a fatal error in memory allocation. This calls png_error if the + * libpng struct is non-NULL, else it outputs a message and returns. This means + * that a memory problem while libpng is running will abort (png_error) the + * handling of particular file while one in cleanup (after the destroy of the + * struct has returned) will simply keep going and free (or attempt to free) + * all the memory. + */ +static void +store_pool_error(png_store *ps, png_structp pp, PNG_CONST char *msg) +{ + if (pp != NULL) + png_error(pp, msg); + + /* Else we have to do it ourselves. png_error eventually calls store_log, + * above. store_log accepts a NULL png_structp - it just changes what gets + * output by store_message. + */ + store_log(ps, pp, msg, 1 /* error */); +} + +static void +store_memory_free(png_structp pp, store_pool *pool, store_memory *memory) +{ + /* Note that pp may be NULL (see store_pool_delete below), the caller has + * found 'memory' in pool->list *and* unlinked this entry, so this is a valid + * pointer (for sure), but the contents may have been trashed. + */ + if (memory->pool != pool) + store_pool_error(pool->store, pp, "memory corrupted (pool)"); + + else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0) + store_pool_error(pool->store, pp, "memory corrupted (start)"); + + /* It should be safe to read the size field now. */ + else + { + png_alloc_size_t cb = memory->size; + + if (cb > pool->max) + store_pool_error(pool->store, pp, "memory corrupted (size)"); + + else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark) + != 0) + store_pool_error(pool->store, pp, "memory corrupted (end)"); + + /* Finally give the library a chance to find problems too: */ + else + { + pool->current -= cb; + free(memory); + } + } +} + +static void +store_pool_delete(png_store *ps, store_pool *pool) +{ + if (pool->list != NULL) + { + fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test, + pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + ++ps->nerrors; + + do + { + store_memory *next = pool->list; + pool->list = next->next; + next->next = NULL; + + fprintf(stderr, "\t%lu bytes @ %p\n", + (unsigned long)next->size, (PNG_CONST void*)(next+1)); + /* The NULL means this will always return, even if the memory is + * corrupted. + */ + store_memory_free(NULL, pool, next); + } + while (pool->list != NULL); + } + + /* And reset the other fields too for the next time. */ + if (pool->max > pool->max_max) pool->max_max = pool->max; + pool->max = 0; + if (pool->current != 0) /* unexpected internal error */ + fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n", + ps->test, pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + pool->current = 0; + + if (pool->limit > pool->max_limit) + pool->max_limit = pool->limit; + + pool->limit = 0; + + if (pool->total > pool->max_total) + pool->max_total = pool->total; + + pool->total = 0; + + /* Get a new mark too. */ + store_pool_mark(pool->mark); +} + +/* The memory callbacks: */ +static png_voidp +store_malloc(png_structp pp, png_alloc_size_t cb) +{ + store_pool *pool = png_get_mem_ptr(pp); + store_memory *new = malloc(cb + (sizeof *new) + (sizeof pool->mark)); + + if (new != NULL) + { + if (cb > pool->max) + pool->max = cb; + + pool->current += cb; + + if (pool->current > pool->limit) + pool->limit = pool->current; + + pool->total += cb; + + new->size = cb; + memcpy(new->mark, pool->mark, sizeof new->mark); + memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark); + new->pool = pool; + new->next = pool->list; + pool->list = new; + ++new; + } + + else + store_pool_error(pool->store, pp, "out of memory"); + + return new; +} + +static void +store_free(png_structp pp, png_voidp memory) +{ + store_pool *pool = png_get_mem_ptr(pp); + store_memory *this = memory, **test; + + /* First check that this 'memory' really is valid memory - it must be in the + * pool list. If it is, use the shared memory_free function to free it. + */ + --this; + for (test = &pool->list; *test != this; test = &(*test)->next) + { + if (*test == NULL) + { + store_pool_error(pool->store, pp, "bad pointer to free"); + return; + } + } + + /* Unlink this entry, *test == this. */ + *test = this->next; + this->next = NULL; + store_memory_free(pp, pool, this); +} + +/* Setup functions. */ +/* Cleanup when aborting a write or after storing the new file. */ +static void +store_write_reset(png_store *ps) +{ + if (ps->pwrite != NULL) + { + anon_context(ps); + + Try + png_destroy_write_struct(&ps->pwrite, &ps->piwrite); + + Catch_anonymous + { + /* memory corruption: continue. */ + } + + ps->pwrite = NULL; + ps->piwrite = NULL; + } + + /* And make sure that all the memory has been freed - this will output + * spurious errors in the case of memory corruption above, but this is safe. + */ + store_pool_delete(ps, &ps->write_memory_pool); + + store_freenew(ps); +} + +/* The following is the main write function, it returns a png_struct and, + * optionally, a png_info suitable for writiing a new PNG file. Use + * store_storefile above to record this file after it has been written. The + * returned libpng structures as destroyed by store_write_reset above. + */ +static png_structp +set_store_for_write(png_store *ps, png_infopp ppi, + PNG_CONST char * volatile name) +{ + anon_context(ps); + + Try + { + if (ps->pwrite != NULL) + png_error(ps->pwrite, "write store already in use"); + + store_write_reset(ps); + safecat(ps->wname, sizeof ps->wname, 0, name); + + /* Don't do the slow memory checks if doing a speed test. */ + if (ps->speed) + ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning); + + else + ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning, &ps->write_memory_pool, + store_malloc, store_free); + + png_set_write_fn(ps->pwrite, ps, store_write, store_flush); + + if (ppi != NULL) + *ppi = ps->piwrite = png_create_info_struct(ps->pwrite); + } + + Catch_anonymous + return NULL; + + return ps->pwrite; +} + +/* Cleanup when finished reading (either due to error or in the success case). + */ +static void +store_read_reset(png_store *ps) +{ + if (ps->pread != NULL) + { + anon_context(ps); + + Try + png_destroy_read_struct(&ps->pread, &ps->piread, NULL); + + Catch_anonymous + { + /* error already output: continue */ + } + + ps->pread = NULL; + ps->piread = NULL; + } + + /* Always do this to be safe. */ + store_pool_delete(ps, &ps->read_memory_pool); + + ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->validated = 0; +} + +static void +store_read_set(png_store *ps, png_uint_32 id) +{ + png_store_file *pf = ps->saved; + + while (pf != NULL) + { + if (pf->id == id) + { + ps->current = pf; + ps->next = NULL; + store_read_buffer_next(ps); + return; + } + + pf = pf->next; + } + + { + size_t pos; + char msg[FILE_NAME_SIZE+64]; + + pos = standard_name_from_id(msg, sizeof msg, 0, id); + pos = safecat(msg, sizeof msg, pos, ": file not found"); + png_error(ps->pread, msg); + } +} + +/* The main interface for reading a saved file - pass the id number of the file + * to retrieve. Ids must be unique or the earlier file will be hidden. The API + * returns a png_struct and, optionally, a png_info. Both of these will be + * destroyed by store_read_reset above. + */ +static png_structp +set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id, + PNG_CONST char *name) +{ + /* Set the name for png_error */ + safecat(ps->test, sizeof ps->test, 0, name); + + if (ps->pread != NULL) + png_error(ps->pread, "read store already in use"); + + store_read_reset(ps); + + /* Both the create APIs can return NULL if used in their default mode + * (because there is no other way of handling an error because the jmp_buf + * by default is stored in png_struct and that has not been allocated!) + * However, given that store_error works correctly in these circumstances + * we don't ever expect NULL in this program. + */ + if (ps->speed) + ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, + store_error, store_warning); + + else + ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps, + store_error, store_warning, &ps->read_memory_pool, store_malloc, + store_free); + + if (ps->pread == NULL) + { + struct exception_context *the_exception_context = &ps->exception_context; + + store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)", + 1 /*error*/); + + Throw ps; + } + + store_read_set(ps, id); + + if (ppi != NULL) + *ppi = ps->piread = png_create_info_struct(ps->pread); + + return ps->pread; +} + +/* The overall cleanup of a store simply calls the above then removes all the + * saved files. This does not delete the store itself. + */ +static void +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; + } +} + +/*********************** PNG FILE MODIFICATION ON READ ************************/ +/* Files may be modified on read. The following structure contains a complete + * png_store together with extra members to handle modification and a special + * read callback for libpng. To use this the 'modifications' field must be set + * to a list of png_modification structures that actually perform the + * modification, otherwise a png_modifier is functionally equivalent to a + * png_store. There is a special read function, set_modifier_for_read, which + * replaces set_store_for_read. + */ +typedef struct png_modifier +{ + png_store this; /* I am a png_store */ + struct png_modification *modifications; /* Changes to make */ + + enum modifier_state + { + modifier_start, /* Initial value */ + modifier_signature, /* Have a signature */ + modifier_IHDR /* Have an IHDR */ + } state; /* My state */ + + /* Information from IHDR: */ + png_byte bit_depth; /* From IHDR */ + png_byte colour_type; /* From IHDR */ + + /* While handling PLTE, IDAT and IEND these chunks may be pended to allow + * other chunks to be inserted. + */ + png_uint_32 pending_len; + png_uint_32 pending_chunk; + + /* Test values */ + double *gammas; + unsigned int ngammas; + + /* Lowest sbit to test (libpng fails for sbit < 8) */ + png_byte sbitlow; + + /* Error control - these are the limits on errors accepted by the gamma tests + * below. + */ + double maxout8; /* Maximum output value error */ + double maxabs8; /* 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 maxpc16; /* Percentage sample error 0..100% */ + + /* Logged 8 and 16 bit errors ('output' values): */ + double error_gray_2; + double error_gray_4; + double error_gray_8; + double error_gray_16; + double error_color_8; + double error_color_16; + + /* Flags: */ + /* Whether or not to interlace. */ + int interlace_type :9; /* int, but must store '1' */ + + /* Run the standard tests? */ + unsigned int test_standard :1; + + /* Run the odd-sized image and interlace read/write tests? */ + unsigned int test_size :1; + + /* Run tests on reading with a combiniation of transforms, */ + unsigned int test_transform :1; + + /* When to use the use_input_precision option: */ + unsigned int use_input_precision :1; + unsigned int use_input_precision_sbit :1; + unsigned int use_input_precision_16to8 :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 log :1; /* Log max error */ + + /* Buffer information, the buffer size limits the size of the chunks that can + * be modified - they must fit (including header and CRC) into the buffer! + */ + size_t flush; /* Count of bytes to flush */ + size_t buffer_count; /* Bytes in buffer */ + size_t buffer_position; /* Position in buffer */ + 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. + */ +static int fail(png_modifier *pm) +{ + return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 || + (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0)); +} + +static void +modifier_init(png_modifier *pm) +{ + memset(pm, 0, sizeof *pm); + store_init(&pm->this); + 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->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->interlace_type = PNG_INTERLACE_NONE; + pm->test_standard = 0; + pm->test_size = 0; + pm->test_transform = 0; + pm->use_input_precision = 0; + pm->use_input_precision_sbit = 0; + pm->use_input_precision_16to8 = 0; + pm->test_gamma_threshold = 0; + pm->test_gamma_transform = 0; + pm->test_gamma_sbit = 0; + pm->test_gamma_strip16 = 0; + pm->log = 0; + + /* Rely on the memset for all the other fields - there are no pointers */ +} + +/* 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 + * suitable chunk does not exist. + * + * The caller of modify_fn will reset the CRC of the chunk and record 'modified' + * or 'added' as appropriate if the modify_fn returns 1 (true). If the + * modify_fn is NULL the chunk is simply removed. + */ +typedef struct png_modification +{ + struct png_modification *next; + png_uint_32 chunk; + + /* If the following is NULL all matching chunks will be removed: */ + int (*modify_fn)(struct png_modifier *pm, + struct png_modification *me, int add); + + /* If the following is set to PLTE, IDAT or IEND and the chunk has not been + * found and modified (and there is a modify_fn) the modify_fn will be called + * to add the chunk before the relevant chunk. + */ + png_uint_32 add; + unsigned int modified :1; /* Chunk was modified */ + unsigned int added :1; /* Chunk was added */ + unsigned int removed :1; /* Chunk was removed */ +} png_modification; + +static void modification_reset(png_modification *pmm) +{ + if (pmm != NULL) + { + pmm->modified = 0; + pmm->added = 0; + pmm->removed = 0; + modification_reset(pmm->next); + } +} + +static void +modification_init(png_modification *pmm) +{ + memset(pmm, 0, sizeof *pmm); + pmm->next = NULL; + pmm->chunk = 0; + pmm->modify_fn = NULL; + pmm->add = 0; + modification_reset(pmm); +} + +static void +modifier_reset(png_modifier *pm) +{ + store_read_reset(&pm->this); + pm->modifications = NULL; + pm->state = modifier_start; + pm->bit_depth = pm->colour_type = 0; + pm->pending_len = pm->pending_chunk = 0; + pm->flush = pm->buffer_count = pm->buffer_position = 0; +} + +/* Convenience macros. */ +#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) +#define CHUNK_IHDR CHUNK(73,72,68,82) +#define CHUNK_PLTE CHUNK(80,76,84,69) +#define CHUNK_IDAT CHUNK(73,68,65,84) +#define CHUNK_IEND CHUNK(73,69,78,68) +#define CHUNK_cHRM CHUNK(99,72,82,77) +#define CHUNK_gAMA CHUNK(103,65,77,65) +#define CHUNK_sBIT CHUNK(115,66,73,84) +#define CHUNK_sRGB CHUNK(115,82,71,66) + +/* The guts of modification are performed during a read. */ +static void +modifier_crc(png_bytep buffer) +{ + /* Recalculate the chunk CRC - a complete chunk must be in + * the buffer, at the start. + */ + uInt datalen = png_get_uint_32(buffer); + png_save_uint_32(buffer+datalen+8, crc32(0L, buffer+4, datalen+4)); +} + +static void +modifier_setbuffer(png_modifier *pm) +{ + modifier_crc(pm->buffer); + pm->buffer_count = png_get_uint_32(pm->buffer)+12; + pm->buffer_position = 0; +} + +/* Separate the callback into the actual implementation (which is passed the + * png_modifier explicitly) and the callback, which gets the modifier from the + * png_struct. + */ +static void +modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st) +{ + while (st > 0) + { + size_t cb; + png_uint_32 len, chunk; + png_modification *mod; + + if (pm->buffer_position >= pm->buffer_count) switch (pm->state) + { + static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + case modifier_start: + store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */ + pm->buffer_count = 8; + pm->buffer_position = 0; + + if (memcmp(pm->buffer, sign, 8) != 0) + png_error(pm->this.pread, "invalid PNG file signature"); + pm->state = modifier_signature; + break; + + case modifier_signature: + store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */ + pm->buffer_count = 13+12; + pm->buffer_position = 0; + + if (png_get_uint_32(pm->buffer) != 13 || + png_get_uint_32(pm->buffer+4) != CHUNK_IHDR) + png_error(pm->this.pread, "invalid IHDR"); + + /* Check the list of modifiers for modifications to the IHDR. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == CHUNK_IHDR && mod->modify_fn && + (*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + modifier_setbuffer(pm); + } + + /* Ignore removal or add if IHDR! */ + mod = mod->next; + } + + /* Cache information from the IHDR (the modified one.) */ + pm->bit_depth = pm->buffer[8+8]; + pm->colour_type = pm->buffer[8+8+1]; + + pm->state = modifier_IHDR; + pm->flush = 0; + break; + + case modifier_IHDR: + default: + /* Read a new chunk and process it until we see PLTE, IDAT or + * IEND. 'flush' indicates that there is still some data to + * output from the preceding chunk. + */ + if ((cb = pm->flush) > 0) + { + if (cb > st) cb = st; + pm->flush -= cb; + store_read_imp(&pm->this, pb, cb); + pb += cb; + st -= cb; + if (st <= 0) return; + } + + /* No more bytes to flush, read a header, or handle a pending + * chunk. + */ + if (pm->pending_chunk != 0) + { + png_save_uint_32(pm->buffer, pm->pending_len); + png_save_uint_32(pm->buffer+4, pm->pending_chunk); + pm->pending_len = 0; + pm->pending_chunk = 0; + } + else + store_read_imp(&pm->this, pm->buffer, 8); + + pm->buffer_count = 8; + pm->buffer_position = 0; + + /* Check for something to modify or a terminator chunk. */ + len = png_get_uint_32(pm->buffer); + chunk = png_get_uint_32(pm->buffer+4); + + /* Terminators first, they may have to be delayed for added + * chunks + */ + if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || + chunk == CHUNK_IEND) + { + mod = pm->modifications; + + while (mod != NULL) + { + if ((mod->add == chunk || + (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) && + mod->modify_fn != NULL && !mod->modified && !mod->added) + { + /* Regardless of what the modify function does do not run + * this again. + */ + mod->added = 1; + + if ((*mod->modify_fn)(pm, mod, 1 /*add*/)) + { + /* Reset the CRC on a new chunk */ + if (pm->buffer_count > 0) + modifier_setbuffer(pm); + + else + { + pm->buffer_position = 0; + mod->removed = 1; + } + + /* The buffer has been filled with something (we assume) + * so output this. Pend the current chunk. + */ + pm->pending_len = len; + pm->pending_chunk = chunk; + break; /* out of while */ + } + } + + mod = mod->next; + } + + /* Don't do any further processing if the buffer was modified - + * otherwise the code will end up modifying a chunk that was + * just added. + */ + if (mod != NULL) + break; /* out of switch */ + } + + /* If we get to here then this chunk may need to be modified. To + * do this it must be less than 1024 bytes in total size, otherwise + * it just gets flushed. + */ + if (len+12 <= sizeof pm->buffer) + { + store_read_imp(&pm->this, pm->buffer+pm->buffer_count, + len+12-pm->buffer_count); + pm->buffer_count = len+12; + + /* Check for a modification, else leave it be. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == chunk) + { + if (mod->modify_fn == NULL) + { + /* Remove this chunk */ + pm->buffer_count = pm->buffer_position = 0; + mod->removed = 1; + break; /* Terminate the while loop */ + } + + else if ((*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + /* The chunk may have been removed: */ + if (pm->buffer_count == 0) + { + pm->buffer_position = 0; + break; + } + modifier_setbuffer(pm); + } + } + + mod = mod->next; + } + } + + else + pm->flush = len+12 - pm->buffer_count; /* data + crc */ + + /* Take the data from the buffer (if there is any). */ + break; + } + + /* Here to read from the modifier buffer (not directly from + * the store, as in the flush case above.) + */ + cb = pm->buffer_count - pm->buffer_position; + + if (cb > st) + cb = st; + + memcpy(pb, pm->buffer + pm->buffer_position, cb); + st -= cb; + pb += cb; + pm->buffer_position += cb; + } +} + +/* The callback: */ +static void +modifier_read(png_structp pp, png_bytep pb, png_size_t st) +{ + png_modifier *pm = png_get_io_ptr(pp); + + if (pm == NULL || pm->this.pread != pp) + png_error(pp, "bad modifier_read call"); + + modifier_read_imp(pm, pb, st); +} + +/* Like store_progressive_read but the data is getting changed as we go so we + * need a local buffer. + */ +static void +modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi) +{ + if (pm->this.pread != pp || pm->this.current == NULL || + pm->this.next == NULL) + png_error(pp, "store state damaged (progressive)"); + + /* This is another Horowitz and Hill random noise generator. In this case + * the aim is to stress the progressive reader with truely horrible variable + * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers + * is generated. We could probably just count from 1 to 32767 and get as + * good a result. + */ + for (;;) + { + static png_uint_32 noise = 1; + png_size_t cb, cbAvail; + png_byte buffer[512]; + + /* Generate 15 more bits of stuff: */ + noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); + cb = noise & 0x1ff; + + /* Check that this number of bytes are available (in the current buffer.) + * (This doesn't quite work - the modifier might delete a chunk; unlikely + * but possible, it doesn't happen at present because the modifier only + * adds chunks to standard images.) + */ + cbAvail = store_read_buffer_avail(&pm->this); + if (pm->buffer_count > pm->buffer_position) + cbAvail += pm->buffer_count - pm->buffer_position; + + if (cb > cbAvail) + { + /* Check for EOF: */ + if (cbAvail == 0) + break; + + cb = cbAvail; + } + + modifier_read_imp(pm, buffer, cb); + png_process_data(pp, pi, buffer, cb); + } + + /* Check the invariants at the end (if this fails it's a problem in this + * file!) + */ + if (pm->buffer_count > pm->buffer_position || + pm->this.next != &pm->this.current->data || + pm->this.readpos < pm->this.current->datacount) + png_error(pp, "progressive read implementation error"); +} + +/* Set up a modifier. */ +static png_structp +set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, + PNG_CONST char *name) +{ + /* Do this first so that the modifier fields are cleared even if an error + * happens allocating the png_struct. No allocation is done here so no + * cleanup is required. + */ + pm->state = modifier_start; + pm->bit_depth = 0; + pm->colour_type = 255; + + pm->pending_len = 0; + pm->pending_chunk = 0; + pm->flush = 0; + pm->buffer_count = 0; + pm->buffer_position = 0; + + return set_store_for_read(&pm->this, ppi, id, name); +} + +/***************************** STANDARD PNG FILES *****************************/ +/* Standard files - write and save standard files. */ +/* There are two basic forms of standard images. Those which attempt to have + * all the possible pixel values (not possible for 16bpp images, but a range of + * values are produced) and those which have a range of image sizes. The former + * are used for testing transforms, in particular gamma correction and bit + * reduction and increase. The latter are reserved for testing the behavior of + * libpng with respect to 'odd' image sizes - particularly small images where + * rows become 1 byte and interlace passes disappear. + * + * The first, most useful, set are the 'transform' images, the second set of + * small images are the 'size' images. + * + * The transform files are constructed with rows which fit into a 1024 byte row + * buffer. This makes allocation easier below. Further regardless of the file + * format every row has 128 pixels (giving 1024 bytes for 64bpp formats). + * + * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed + * and with an ID derived from the colour type, bit depth and interlace type + * as above (FILEID). The width (128) and height (variable) are not stored in + * the FILEID - instead the fields are set to 0, indicating a transform file. + * + * The size files ar constructed with rows a maximum of 128 bytes wide, allowing + * 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. + */ + +/* The number of passes is related to the interlace type. There wass no libpng + * API to determine this prior to 1.5, so we need an inquiry function: + */ +static int +npasses_from_interlace_type(png_structp pp, int interlace_type) +{ + switch (interlace_type) + { + default: + png_error(pp, "invalid interlace type"); + + case PNG_INTERLACE_NONE: + return 1; + + case PNG_INTERLACE_ADAM7: + return PNG_INTERLACE_ADAM7_PASSES; + } +} + +static unsigned int +bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (colour_type) + { + case 0: return bit_depth; + + case 2: return 3*bit_depth; + + case 3: return bit_depth; + + case 4: return 2*bit_depth; + + case 6: return 4*bit_depth; + + default: png_error(pp, "invalid color type"); + } +} + +#define TRANSFORM_WIDTH 128U +#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) + +static size_t +transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8; +} + +/* transform_width(pp, colour_type, bit_depth) current returns the same number + * every time, so just use a macro: + */ +#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH + +static png_uint_32 +transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + case 2: + case 4: + return 1; /* Total of 128 pixels */ + + case 8: + return 2; /* Total of 256 pixels/bytes */ + + case 16: + return 512; /* Total of 65536 pixels */ + + case 24: + case 32: + return 512; /* 65536 pixels */ + + case 48: + case 64: + return 2048;/* 4 x 65536 pixels. */ + + default: + return 0; /* Error, will be caught later */ + } +} + +/* The following can only be defined here, now we have the definitions + * of the transform image sizes. + */ +static png_uint_32 +standard_width(png_structp pp, png_uint_32 id) +{ + png_uint_32 width = WIDTH_FROM_ID(id); + UNUSED(pp) + + if (width == 0) + width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return width; +} + +static png_uint_32 +standard_height(png_structp pp, png_uint_32 id) +{ + png_uint_32 height = HEIGHT_FROM_ID(id); + + if (height == 0) + height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return height; +} + +static png_uint_32 +standard_rowsize(png_structp pp, png_uint_32 id) +{ + png_uint_32 width = standard_width(pp, id); + + /* This won't overflow: */ + width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + return (width + 7) / 8; +} + +static void +transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX], + png_byte colour_type, png_byte bit_depth, png_uint_32 y) +{ + png_uint_32 v = y << 7; + png_uint_32 i = 0; + + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i; + return; + + case 2: + while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i; + return; + + case 4: + while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i; + return; + + case 8: + /* 256 bytes total, 128 bytes in each row set as follows: */ + while (i<128) buffer[i] = v & 0xff, ++v, ++i; + return; + + case 16: + /* Generate all 65536 pixel values in order, which includes the 8 bit + * GA case as well as the 16 bit G case. + */ + while (i<128) + buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i; + + return; + + case 24: + /* 65535 pixels, but rotate the values. */ + while (i<128) + { + /* Three bytes per pixel, r, g, b, make b by r^g */ + buffer[3*i+0] = (v >> 8) & 0xff; + buffer[3*i+1] = v & 0xff; + buffer[3*i+2] = ((v >> 8) ^ v) & 0xff; + ++v; + ++i; + } + + return; + + case 32: + /* 65535 pixels, r, g, b, a; just replicate */ + while (i<128) + { + buffer[4*i+0] = (v >> 8) & 0xff; + buffer[4*i+1] = v & 0xff; + buffer[4*i+2] = (v >> 8) & 0xff; + buffer[4*i+3] = v & 0xff; + ++v; + ++i; + } + + return; + + case 48: + /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at + * each pixel, g increase by 257 (0x101) and 'b' by 0x1111: + */ + while (i<128) + { + png_uint_32 t = v++; + buffer[6*i+0] = (t >> 8) & 0xff; + buffer[6*i+1] = t & 0xff; + t *= 257; + buffer[6*i+2] = (t >> 8) & 0xff; + buffer[6*i+3] = t & 0xff; + t *= 17; + buffer[6*i+4] = (t >> 8) & 0xff; + buffer[6*i+5] = t & 0xff; + ++i; + } + + return; + + case 64: + /* As above in the 32 bit case. */ + while (i<128) + { + png_uint_32 t = v++; + buffer[8*i+0] = (t >> 8) & 0xff; + buffer[8*i+1] = t & 0xff; + buffer[8*i+4] = (t >> 8) & 0xff; + buffer[8*i+5] = t & 0xff; + t *= 257; + buffer[8*i+2] = (t >> 8) & 0xff; + buffer[8*i+3] = t & 0xff; + buffer[8*i+6] = (t >> 8) & 0xff; + buffer[8*i+7] = t & 0xff; + ++i; + } + return; + + default: + break; + } + + png_error(pp, "internal error"); +} + +/* This is just to do the right cast - could be changed to a function to check + * 'bd' but there isn't much point. + */ +#define DEPTH(bd) ((png_byte)(1U << (bd))) + +/* Make a standardized image given a an image colour type, bit depth and + * interlace type. The standard images have a very restricted range of + * rows and heights and are used for testing transforms rather than image + * layout details. See make_size_images below for a way to make images + * that test odd sizes along with the libpng interlace handling. + */ +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) +{ + context(ps, fault); + + Try + { + png_infop pi; + png_structp pp = set_store_for_write(ps, &pi, name); + png_uint_32 h; + + /* In the event of a problem return control to the Catch statement below + * to do the clean up - it is not possible to 'return' directly from a Try + * block. + */ + if (pp == NULL) + Throw ps; + + h = transform_height(pp, colour_type, bit_depth); + + png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h, + bit_depth, 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); + + png_set_PLTE(pp, pi, pal, 256); + } + + png_write_info(pp, pi); + + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "row size incorrect"); + + else + { + /* Somewhat confusingly this must be called *after* png_write_info + * because if it is called before, the information in *pp has not been + * updated to reflect the interlaced image. + */ + int npasses = png_set_interlace_handling(pp); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; passtest, 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. + */ +static void +interlace_row(png_bytep buffer, png_const_bytep imageRow, + unsigned int pixel_size, png_uint_32 w, int pass) +{ + png_uint_32 xin, xout, xstep; + + /* Note that this can, trivially, be optimized to a memcpy on pass 7, the + * code is presented this way to make it easier to understand. In practice + * consult the code in the libpng source to see other ways of doing this. + */ + xin = PNG_PASS_START_COL(pass); + xstep = 1U<= 8) + *buffer++ = (png_byte)y++, bit_width -= 8; + + /* There may be up to 7 remaining bits, these go in the most significant + * bits of the byte. + */ + if (bit_width > 0) + { + png_uint_32 mask = (1U<<(8-bit_width))-1; + *buffer = (png_byte)((*buffer & mask) | (y & ~mask)); + } +} + +static void +make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, + png_byte PNG_CONST bit_depth, int PNG_CONST interlace_type, + png_uint_32 PNG_CONST w, png_uint_32 PNG_CONST h, + int PNG_CONST do_interlace) +{ + context(ps, fault); + + Try + { + png_infop pi; + png_structp pp; + unsigned int pixel_size; + + /* 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); + + standard_name_from_id(name, sizeof name, 0, id); + pp = set_store_for_write(ps, &pi, name); + + /* In the event of a problem return control to the Catch statement below + * to do the clean up - it is not possible to 'return' directly from a Try + * block. + */ + if (pp == NULL) + Throw ps; + + 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); + } + + png_write_info(pp, pi); + + /* Calculate the bit size, divide by 8 to get the byte size - this won't + * overflow because we know the w values are all small enough even for + * a system where 'unsigned int' is only 16 bits. + */ + pixel_size = bit_size(pp, colour_type, bit_depth); + if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8) + png_error(pp, "row size incorrect"); + + else + { + int npasses = npasses_from_interlace_type(pp, interlace_type); + png_uint_32 y; + int pass; + png_byte image[16][SIZE_ROWMAX]; + + /* To help consistent error detection make the parts of this buffer + * that aren't set below all '1': + */ + memset(image, 0xff, sizeof image); + + if (!do_interlace && npasses != png_set_interlace_handling(pp)) + png_error(pp, "write: png_set_interlace_handling failed"); + + /* Prepare the whole image first to avoid making it 7 times: */ + for (y=0; y 0) + { + /* Set to all 1's for error detection (libpng tends to + * set unset things to 0). + */ + memset(tempRow, 0xff, sizeof tempRow); + interlace_row(tempRow, row, pixel_size, w, pass); + row = tempRow; + } + else + continue; + } + + /* Only get to here if the row has some pixels in it. */ + png_write_row(pp, row); + } + } + } + + png_write_end(pp, pi); + + /* And store this under the appropriate id, then clean up. */ + store_storefile(ps, id); + + store_write_reset(ps); + } + + Catch(fault) + { + /* Use the png_store returned by the exception. This may help the compiler + * because 'ps' is not used in this branch of the setjmp. Note that fault + * and ps will always be the same value. + */ + store_write_reset(fault); + } +} + +static void +make_size(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo, + int PNG_CONST bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 width; + + for (width = 1; width <= 16; ++width) + { + png_uint_32 height; + + for (height = 1; height <= 16; ++height) + { + /* The four combinations of DIY interlace and interlace or not - + * no interlace + DIY should be identical to no interlace with + * libpng doing it. + */ + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 0); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 1); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 0); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 1); + } + } + } +} + +static void +make_size_images(png_store *ps) +{ + /* This is in case of errors. */ + safecat(ps->test, sizeof ps->test, 0, "make size images"); + + /* Arguments are colour_type, low bit depth, high bit depth + */ + make_size(ps, 0, 0, WRITE_BDHI); + make_size(ps, 2, 3, WRITE_BDHI); + make_size(ps, 3, 0, 3 /*palette: max 8 bits*/); + make_size(ps, 4, 3, WRITE_BDHI); + make_size(ps, 6, 3, WRITE_BDHI); +} + +/* Return a row based on image id and 'y' for checking: */ +static void +standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id, + png_uint_32 y) +{ + if (WIDTH_FROM_ID(id) == 0) + transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y); + else + size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id), + DEPTH_FROM_ID(id)), y); +} + +/* Tests - individual test cases */ +/* Like 'make_standard' but errors are deliberately introduced into the calls + * to ensure that they get detected - it should not be possible to write an + * invalid image with libpng! + */ +static void +sBIT0_error_fn(png_structp pp, png_infop pi) +{ + /* 0 is invalid... */ + png_color_8 bad; + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0; + png_set_sBIT(pp, pi, &bad); +} + +static void +sBIT_error_fn(png_structp pp, png_infop pi) +{ + png_byte bit_depth; + png_color_8 bad; + + if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE) + bit_depth = 8; + + else + bit_depth = png_get_bit_depth(pp, pi); + + /* Now we know the bit depth we can easily generate an invalid sBIT entry */ + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = + (png_byte)(bit_depth+1); + png_set_sBIT(pp, pi, &bad); +} + +static PNG_CONST struct +{ + void (*fn)(png_structp, png_infop); + PNG_CONST char *msg; + unsigned int warning :1; /* the error is a warning... */ +} error_test[] = + { + { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 }, + { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 }, + }; + +static void +make_error(png_store* volatile ps, png_byte PNG_CONST colour_type, + png_byte bit_depth, int interlace_type, int test, png_const_charp name) +{ + context(ps, fault); + + Try + { + png_structp pp; + png_infop pi; + + pp = set_store_for_write(ps, &pi, name); + + if (pp == NULL) + Throw ps; + + png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), + transform_height(pp, colour_type, bit_depth), bit_depth, 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); + + png_set_PLTE(pp, pi, pal, 256); + } + + /* 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 +# define exception__env exception_env_1 + Try + { + /* Expect this to throw: */ + ps->expect_error = !error_test[test].warning; + ps->expect_warning = error_test[test].warning; + ps->saw_warning = 0; + error_test[test].fn(pp, pi); + + /* Normally the error is only detected here: */ + png_write_info(pp, pi); + + /* And handle the case where it was only a warning: */ + if (ps->expect_warning && ps->saw_warning) + Throw ps; + + /* If we get here there is a problem, we have success - no error or + * no warning - when we shouldn't have success. Log an error. + */ + store_log(ps, pp, error_test[test].msg, 1 /*error*/); + } + + Catch (fault) + ps = fault; /* expected exit, make sure ps is not clobbered */ +#undef exception__prev +#undef exception__env + + /* And clear these flags */ + ps->expect_error = 0; + ps->expect_warning = 0; + + /* Now write the whole image, just to make sure that the detected, or + * undetected, errro has not created problems inside libpng. + */ + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "row size incorrect"); + + else + { + png_uint_32 h = transform_height(pp, colour_type, bit_depth); + int npasses = png_set_interlace_handling(pp); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; passthis, colour_type, DEPTH(bdlo), interlace_type, + test, name); + + if (fail(pm)) + return 0; + } + } + } + + return 1; /* keep going */ +} + +static void +perform_error_test(png_modifier *pm) +{ + /* Need to do this here because we just write in this test. */ + safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); + + if (!make_errors(pm, 0, 0, WRITE_BDHI)) + return; + + if (!make_errors(pm, 2, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 3, 0, 3)) + return; + + if (!make_errors(pm, 4, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 6, 3, WRITE_BDHI)) + return; +} + +/* Because we want to use the same code in both the progressive reader and the + * sequential reader it is necessary to deal with the fact that the progressive + * reader callbacks only have one parameter (png_get_progressive_ptr()), so this + * must contain all the test parameters and all the local variables directly + * accessible to the sequential reader implementation. + * + * The technique adopted is to reinvent part of what Dijkstra termed a + * 'display'; an array of pointers to the stack frames of enclosing functions so + * that a nested function definition can access the local (C auto) variables of + * the functions that contain its definition. In fact C provides the first + * pointer (the local variables - the stack frame pointer) and the last (the + * global variables - the BCPL global vector typically implemented as global + * addresses), this code requires one more pointer to make the display - the + * local variables (and function call parameters) of the function that actually + * invokes either the progressive or sequential reader. + * + * Perhaps confusingly this technique is confounded with classes - the + * 'standard_display' defined here is sub-classed as the 'gamma_display' below. + * A gamma_display is a standard_display, taking advantage of the ANSI-C + * 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! + */ +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) */ + png_byte colour_type; + png_byte bit_depth; + png_byte red_sBIT; /* Input data sBIT values. */ + png_byte green_sBIT; + png_byte blue_sBIT; + png_byte alpha_sBIT; + int interlace_type; + png_uint_32 id; /* Calculated file ID */ + png_uint_32 w; /* Width of image */ + png_uint_32 h; /* Height of image */ + int npasses; /* Number of interlaced passes */ + png_uint_32 pixel_size; /* Width of one pixel in bits */ + 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. */ + struct + { + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + } transparent; /* The transparent color, if set. */ + standard_palette + palette; +} standard_display; + +static void +standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, + int do_interlace) +{ + 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; + dp->interlace_type = INTERLACE_FROM_ID(id); + dp->id = id; + /* All the rest are filled in after the read_info: */ + dp->w = 0; + dp->h = 0; + dp->npasses = 0; + dp->pixel_size = 0; + dp->bit_width = 0; + dp->cbRow = 0; + dp->do_interlace = do_interlace; + dp->is_transparent = 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); + +} + +/* 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. + */ +static int +standard_palette_init(standard_palette palette, 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) + { + int i; + + for (i=0; i 256) + png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); + + for (i=0; ibit_depth) + png_error(pp, "validate: bit depth changed"); + + if (png_get_color_type(pp, pi) != dp->colour_type) + png_error(pp, "validate: color type changed"); + + if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE) + png_error(pp, "validate: filter type changed"); + + if (png_get_interlace_type(pp, pi) != dp->interlace_type) + png_error(pp, "validate: interlacing changed"); + + if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE) + png_error(pp, "validate: compression type changed"); + + dp->w = png_get_image_width(pp, pi); + + if (dp->w != standard_width(pp, dp->id)) + png_error(pp, "validate: image width changed"); + + dp->h = png_get_image_height(pp, pi); + + if (dp->h != standard_height(pp, dp->id)) + png_error(pp, "validate: image height changed"); + + /* Record (but don't check at present) the input sBIT according to the colour + * type information. + */ + { + png_color_8p sBIT = 0; + + if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT) + { + int sBIT_invalid = 0; + + if (sBIT == 0) + png_error(pp, "validate: unexpected png_get_sBIT result"); + + if (dp->colour_type & PNG_COLOR_MASK_COLOR) + { + if (sBIT->red == 0 || sBIT->red > dp->bit_depth) + sBIT_invalid = 1; + else + dp->red_sBIT = sBIT->red; + + if (sBIT->green == 0 || sBIT->green > dp->bit_depth) + sBIT_invalid = 1; + else + dp->green_sBIT = sBIT->green; + + if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = sBIT->blue; + } + + else /* !COLOR */ + { + if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray; + } + + /* All 8 bits in tRNS for a palette image are significant - see the + * spec. + */ + if (dp->colour_type & PNG_COLOR_MASK_ALPHA) + { + if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth) + sBIT_invalid = 1; + else + dp->alpha_sBIT = sBIT->alpha; + } + + if (sBIT_invalid) + png_error(pp, "validate: sBIT value out of range"); + } + } + + /* Important: this is validating the value *before* any transforms have been + * put in place. It doesn't matter for the standard tests, where there are + * no transforms, but it does for other tests where rowbytes may change after + * png_read_update_info. + */ + 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. + */ + 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"); + } + + /* In any case always check for a tranparent color: */ + { + png_color_16p trans_color = 0; + + if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS) + { + if (trans_color == 0) + png_error(pp, "validate: unexpected png_get_tRNS (color) result"); + + switch (dp->colour_type) + { + case 0: + dp->transparent.red = dp->transparent.green = dp->transparent.blue = + trans_color->gray; + dp->is_transparent = 1; + break; + + case 2: + dp->transparent.red = trans_color->red; + dp->transparent.green = trans_color->green; + dp->transparent.blue = trans_color->blue; + dp->is_transparent = 1; + break; + + case 3: + /* Not expected because it should result in the array case + * above. + */ + png_error(pp, "validate: unexpected png_get_tRNS result"); + break; + + default: + png_error(pp, "validate: invalid tRNS chunk with alpha image"); + } + } + } + + /* Read the number of passes - expected to match the value used when + * creating the image (interlaced or not). This has the side effect of + * turning on interlace handling (if do_interlace is not set.) + */ + dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type); + if (!dp->do_interlace && dp->npasses != png_set_interlace_handling(pp)) + png_error(pp, "validate: file changed interlace type"); + + /* Caller calls png_read_update_info or png_start_read_image now, then calls + * part2. + */ +} + +/* This must be called *after* the png_read_update_info call to get the correct + * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed + * image. + */ +static void +standard_info_part2(standard_display *dp, png_structp pp, png_infop pi, + int nImages) +{ + /* Record cbRow now that it can be found. */ + dp->pixel_size = bit_size(pp, png_get_color_type(pp, pi), + png_get_bit_depth(pp, pi)); + dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size; + dp->cbRow = png_get_rowbytes(pp, pi); + + /* Validate the rowbytes here again. */ + if (dp->cbRow != (dp->bit_width+7)/8) + 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); +} + +static void +standard_info_imp(standard_display *dp, png_structp pp, png_infop pi, + int nImages) +{ + /* Note that the validation routine has the side effect of turning on + * interlace handling in the subsequent code. + */ + standard_info_part1(dp, pp, pi); + + /* And the info callback has to call this (or png_read_update_info - see + * below in the png_modifier code for that variant. + */ + png_start_read_image(pp); + + /* Validate the height, width and rowbytes plus ensure that sufficient buffer + * exists for decoding the image. + */ + standard_info_part2(dp, pp, pi, nImages); +} + +static void +standard_info(png_structp pp, png_infop pi) +{ + standard_display *dp = png_get_progressive_ptr(pp); + + /* Call with nImages==1 because the progressive reader can only produce one + * image. + */ + standard_info_imp(dp, pp, pi, 1 /*only one image*/); +} + +static void +progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) +{ + PNG_CONST standard_display *dp = png_get_progressive_ptr(pp); + + /* When handling interlacing some rows will be absent in each pass, the + * callback still gets called, but with a NULL pointer. This is checked + * in the 'else' clause below. We need our own 'cbRow', but we can't call + * png_get_rowbytes because we got no info structure. + */ + if (new_row != NULL) + { + png_bytep row; + + /* In the case where the reader doesn't do the interlace it gives + * us the y in the sub-image: + */ + if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) + { + /* 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"); + + 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; + + /* Combine the new row into the old: */ + if (dp->do_interlace) + { + if (dp->interlace_type == PNG_INTERLACE_ADAM7) + deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass); + else + memcpy(row, new_row, dp->cbRow); + } + else + png_progressive_combine_row(pp, row, new_row); + } else if (dp->interlace_type == PNG_INTERLACE_ADAM7 && + PNG_ROW_IN_INTERLACE_PASS(y, pass) && + PNG_PASS_COLS(dp->w, pass) > 0) + png_error(pp, "missing row in progressive de-interlacing"); +} + +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 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; + int pass; + + for (pass=0; pass 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass)) + { + /* Read the row into a pair of temporary buffers, then do the + * merge here into the output rows. + */ + png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX]; + + /* The following aids (to some extent) error detection - we can + * see where png_read_row wrote. Use opposite values in row and + * display to make this easier. + */ + memset(row, 0xff, sizeof row); + memset(display, 0, sizeof display); + + png_read_row(pp, row, display); + + if (pRow1 != NULL) + deinterlace_row(pRow1, row, dp->pixel_size, dp->w, pass); + + if (pRow2 != NULL) + deinterlace_row(pRow2, display, dp->pixel_size, dp->w, pass); + } + } + else + png_read_row(pp, pRow1, pRow2); + + if (pRow1 != NULL) + pRow1 += cbRow; + + if (pRow2 != NULL) + pRow2 += cbRow; + } + } + + /* And finish the read operation (only really necessary if the caller wants + * to find additional data in png_info from chunks after the last IDAT.) + */ + png_read_end(pp, pi); +} + +static void +standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, + png_const_bytep display, png_uint_32 y) +{ + png_byte std[STANDARD_ROWMAX]; + + memset(std, 0xff, sizeof std); + standard_row(pp, std, dp->id, y); + + /* At the end both the 'row' and 'display' arrays should end up identical. + * In earlier passes 'row' will be partially filled in, with only the pixels + * that have been read so far, but 'display' will have those pixels + * replicated to fill the unread pixels while reading an interlaced image. + * The side effect inside the libpng sequential reader is that the 'row' + * array retains the correct values for unwritten pixels within the row + * bytes, while the 'display' array gets bits off the end of the image (in + * the last byte) trashed. Unfortunately in the progressive reader the + * 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) + { + char msg[64]; + sprintf(msg, "PNG image row %d changed", y); + png_error(pp, msg); + } + + /* In this case use pixel_cmp because we need to compare a partial + * 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) + { + char msg[64]; + sprintf(msg, "display row %d changed", y); + png_error(pp, msg); + } +} + +static void +standard_image_validate(standard_display *dp, png_structp pp, + png_const_bytep pImage, png_const_bytep pDisplay) +{ + png_uint_32 y; + + for (y=0; yh; ++y) + { + standard_row_validate(dp, pp, pImage, pDisplay, y); + + if (pImage != NULL) + pImage += dp->cbRow; + + if (pDisplay != NULL) + pDisplay += dp->cbRow; + } + + /* This avoids false positives if the validation code is never called! */ + dp->ps->validated = 1; +} + +static void +standard_end(png_structp pp, png_infop pi) +{ + standard_display *dp = png_get_progressive_ptr(pp); + + UNUSED(pi) + + /* Validate the image - progressive reading only produces one variant for + * interlaced images. + */ + standard_image_validate(dp, pp, dp->ps->image, NULL); +} + +/* A single test run checking the standard image to ensure it is not damaged. */ +static void +standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id, + int do_interlace) +{ + standard_display d; + context(psIn, fault); + + /* Set up the display (stack frame) variables from the arguments to the + * function and initialize the locals that are filled in later. + */ + standard_display_init(&d, psIn, id, do_interlace); + + /* Everything is protected by a Try/Catch. The functions called also + * typically have local Try/Catch blocks. + */ + Try + { + png_structp pp; + png_infop pi; + + /* Get a png_struct for reading the image. This will throw an error if it + * fails, so we don't need to check the result. + */ + pp = set_store_for_read(d.ps, &pi, d.id, + d.do_interlace ? (d.ps->progressive ? + "pngvalid progressive deinterlacer" : + "pngvalid sequential deinterlacer") : (d.ps->progressive ? + "progressive reader" : "sequential reader")); + + /* Introduce the correct read function. */ + if (d.ps->progressive) + { + png_set_progressive_read_fn(pp, &d, standard_info, progressive_row, + standard_end); + + /* Now feed data into the reader until we reach the end: */ + store_progressive_read(d.ps, pp, pi); + } + else + { + /* Note that this takes the store, not the display. */ + png_set_read_fn(pp, d.ps, store_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* The code tests both versions of the images that the sequential + * reader can produce. + */ + standard_info_imp(&d, pp, pi, 2 /*images*/); + + /* Need the total bytes in the image below; we can't get to this point + * unless the PNG file values have been checked against the expected + * 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); + + /* After the last pass loop over the rows again to check that the + * image is correct. + */ + standard_image_validate(&d, pp, pImage, pDisplay); + } + } + + /* Check for validation. */ + if (!d.ps->validated) + png_error(pp, "image read failed silently"); + + /* Successful completion. */ + } + + Catch(fault) + d.ps = fault; /* make sure this hasn't been clobbered. */ + + /* In either case clean up the store. */ + store_read_reset(d.ps); +} + +static int +test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, + int bdlo, int PNG_CONST bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + int interlace_type; + + for (interlace_type = PNG_INTERLACE_NONE; + interlace_type < PNG_INTERLACE_LAST; ++interlace_type) + { + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + interlace_type, 0, 0, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_standard_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_standard(pm, 0, 0, READ_BDHI)) + return; + + if (!test_standard(pm, 2, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 3, 0, 3)) + return; + + if (!test_standard(pm, 4, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 6, 3, READ_BDHI)) + return; +} + + +/********************************** SIZE TESTS ********************************/ +static int +test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, + int bdlo, int PNG_CONST bdhi) +{ + /* Run the tests on each combination. + * + * NOTE: on my 32 bit x86 each of the following blocks takes + * a total of 3.5 seconds if done across every combo of bit depth + * width and height. This is a waste of time in practice, hence the + * hinc and winc stuff: + */ + static PNG_CONST png_byte hinc[] = {1, 3, 11, 1, 5}; + static PNG_CONST png_byte winc[] = {1, 9, 5, 7, 1}; + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 h, w; + + for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) + { + /* First test all the 'size' images against the sequential + * reader using libpng to deinterlace (where required.) This + * validates the write side of libpng. There are four possibilities + * to validate. + */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + /* Now validate the interlaced read side - do_interlace true, + * 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), + PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_size_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_size(pm, 0, 0, READ_BDHI)) + return; + + if (!test_size(pm, 2, 3, READ_BDHI)) + return; + + /* For the moment don't do the palette test - it's a waste of time when + * compared to the greyscale test. + */ +#if 0 + if (!test_size(pm, 3, 0, 3)) + return; +#endif + + if (!test_size(pm, 4, 3, READ_BDHI)) + return; + + if (!test_size(pm, 6, 3, READ_BDHI)) + return; +} + + +/******************************* TRANSFORM TESTS ******************************/ +/* 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 + * the tests would take forever. + */ +typedef struct image_pixel +{ + /* A local (pngvalid) representation of a PNG pixel, in all its + * various forms. + */ + unsigned int red, green, blue, alpha; /* For non-palette images. */ + unsigned int palette_index; /* For a palette image. */ + png_byte colour_type; /* As in the spec. */ + png_byte bit_depth; /* Defines bit size in row */ + png_byte sample_depth; /* Scale of samples */ + int have_tRNS; /* tRNS chunk may need processing */ + + /* For checking the code calculates double precision floating point values + * along with an error value, accumulated from the transforms. Because an + * sBIT setting allows larger error bounds (indeed, by the spec, apparently + * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each + * channel is stored. This sBIT value is folded in to the stored error value + * at the end of the application of the transforms to the pixel. + */ + double redf, greenf, bluef, alphaf; + double rede, greene, bluee, alphae; + png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT; +} image_pixel; + +/* Shared utility function, see below. */ +static void +image_pixel_setf(image_pixel *this, unsigned int max) +{ + this->redf = this->red / (double)max; + this->greenf = this->green / (double)max; + this->bluef = this->blue / (double)max; + this->alphaf = this->alpha / (double)max; + + if (this->red < max) + this->rede = this->redf * DBL_EPSILON; + else + this->rede = 0; + if (this->green < max) + this->greene = this->greenf * DBL_EPSILON; + else + this->greene = 0; + if (this->blue < max) + this->bluee = this->bluef * DBL_EPSILON; + else + this->bluee = 0; + if (this->alpha < max) + this->alphae = this->alphaf * DBL_EPSILON; + else + this->alphae = 0; +} + +/* Initialize the structure for the next pixel - call this before doing any + * transforms and call it for each pixel since all the fields may need to be + * reset. + */ +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_CONST png_byte sample_depth = (png_byte)(colour_type == + PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); + PNG_CONST unsigned int max = (1U<palette_index = this->red = this->green = this->blue = + sample(row, colour_type, bit_depth, x, 0); + this->alpha = max; + this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT = + sample_depth; + + /* Then override as appropriate: */ + if (colour_type == 3) /* palette */ + { + /* This permits the caller to default to the sample value. */ + if (palette != 0) + { + PNG_CONST unsigned int i = this->palette_index; + + this->red = palette[i].red; + this->green = palette[i].green; + this->blue = palette[i].blue; + this->alpha = palette[i].alpha; + } + } + + else /* not palette */ + { + unsigned int i = 0; + + if (colour_type & 2) + { + this->green = sample(row, colour_type, bit_depth, x, 1); + this->blue = sample(row, colour_type, bit_depth, x, 2); + i = 2; + } + if (colour_type & 4) + this->alpha = sample(row, colour_type, bit_depth, x, ++i); + } + + /* Calculate the scaled values, these are simply the values divided by + * 'max' and the error is initialized to the double precision epsilon value + * from the header file. + */ + image_pixel_setf(this, max); + + /* Store the input information for use in the transforms - these will + * modify the information. + */ + this->colour_type = colour_type; + this->bit_depth = bit_depth; + this->sample_depth = sample_depth; + this->have_tRNS = 0; +} + +/* 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. + */ +static void +image_pixel_convert_PLTE(image_pixel *this, const standard_display *display) +{ + 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. + */ + image_pixel_setf(this, 255); + } +} + +/* Add an alpha channel, this will glom in 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). + */ +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); + + if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) + { + if (this->colour_type == PNG_COLOR_TYPE_GRAY) + { + if (this->bit_depth < 8) + this->bit_depth = 8; + + if (this->have_tRNS) + { + this->have_tRNS = 0; + + /* Check the input, original, channel value here against the + * original tRNS gray chunk valie. + */ + if (this->red == display->transparent.red) + this->alphaf = 0; + else + this->alphaf = 1; + } + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + else if (this->colour_type == PNG_COLOR_TYPE_RGB) + { + if (this->have_tRNS) + { + this->have_tRNS = 0; + + /* Again, check the exact input values, not the current transformed + * value! + */ + if (this->red == display->transparent.red && + this->green == display->transparent.green && + this->blue == display->transparent.blue) + this->alphaf = 0; + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + } + + /* The error in the alpha is zero and the sBIT value comes from the + * original sBIT data (actually it will always be the original bit depth). + */ + this->alphae = 0; + this->alpha_sBIT = display->alpha_sBIT; + } +} + +struct transform_display; +typedef struct image_transform +{ + /* The name of this transform: a string. */ + PNG_CONST char *name; + + /* Each transform can be disabled from the command line: */ + int enable; + + /* The global list of transforms; read only. */ + struct image_transform *PNG_CONST list; + + /* The global count of the number of times this transform has been set on an + * image. + */ + unsigned int global_use; + + /* The local count of the number of times this transform has been set. */ + unsigned int local_use; + + /* The next transform in the list, each transform must call its own next + * transform after it has processed the pixel successfully. + */ + PNG_CONST struct image_transform *next; + + /* A single transform for the image, expressed as a series of function + * callbacks and some space for values. + * + * First a callback to set the transform on the current png_read_struct: + */ + void (*set)(PNG_CONST struct image_transform *this, + struct transform_display *that, png_structp pp, png_infop pi); + + /* Then a transform that takes an input pixel in one PNG format or another + * and modifies it by a pngvalid implementation of the transform (thus + * duplicating the libpng intent without, we hope, duplicating the bugs + * in the libpng implementation!) The png_structp is solely to allow error + * reporting via png_error and png_warning. + */ + void (*mod)(PNG_CONST struct image_transform *this, image_pixel *that, + png_structp pp, PNG_CONST struct transform_display *display); + + /* Add this transform to the list and return true if the transform is + * meaningful for this colour type and bit depth - if false then the + * transform should have no effect on the image so there's not a lot of + * point running it. + */ + int (*add)(struct image_transform *this, + PNG_CONST struct image_transform **that, png_byte colour_type, + png_byte bit_depth); +} image_transform; + +typedef struct transform_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + PNG_CONST image_transform* transform_list; + + /* Local variables */ + png_byte output_colour_type; + png_byte output_bit_depth; +} transform_display; + +/* Two functions to end the list: */ +static void +image_transform_set_end(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + UNUSED(this) + UNUSED(that) + UNUSED(pp) + UNUSED(pi) +} + +/* At the end of the list recalculate the output image pixel value from the + * double precision values set up by the preceding 'mod' calls: + */ +static unsigned int +sample_scale(double sample_value, unsigned int scale) +{ + sample_value = floor(sample_value * scale + .5); + + /* Return NaN as 0: */ + if (!(sample_value > 0)) + sample_value = 0; + else if (sample_value > scale) + sample_value = scale; + + return (unsigned int)sample_value; +} + +static void +image_transform_mod_end(PNG_CONST image_transform *this, image_pixel *that, + png_structp pp, PNG_CONST transform_display *display) +{ + PNG_CONST unsigned int scale = (1U<sample_depth)-1; + + UNUSED(this) + UNUSED(pp) + UNUSED(display) + + /* At the end recalculate the digitized red green and blue values according + * to the current sample_depth of the pixel. + * + * The sample value is simply scaled to the maximum, checking for over + * and underflow (which can both happen for some image transforms, + * including simple size scaling, though libpng doesn't do that at present. + */ + that->red = sample_scale(that->redf, scale); + + /* The error value is increased, at the end, according to the lowest sBIT + * value seen. Common sense tells us that the intermediate integer + * representations are no more accurate than +/- 0.5 in the integral values, + * the sBIT allows the implementation to be worse than this. In addition the + * PNG specification actually permits any error within the range (-1..+1), + * but that is ignored here. Instead the final digitized value is compared, + * below to the digitized value of the error limits - this has the net effect + * of allowing (almost) +/-1 in the output value. It's difficult to see how + * any algorithm that digitizes intermediate results can be more accurate. + */ + that->rede += 1./(2*((1U<red_sBIT)-1)); + + if (that->colour_type & PNG_COLOR_MASK_COLOR) + { + that->green = sample_scale(that->greenf, scale); + that->blue = sample_scale(that->bluef, scale); + that->greene += 1./(2*((1U<green_sBIT)-1)); + that->bluee += 1./(2*((1U<blue_sBIT)-1)); + } + else + { + that->blue = that->green = that->red; + that->bluef = that->greenf = that->redf; + that->bluee = that->greene = that->rede; + } + + if ((that->colour_type & PNG_COLOR_MASK_ALPHA) || + that->colour_type == PNG_COLOR_TYPE_PALETTE) + { + that->alpha = sample_scale(that->alphaf, scale); + that->alphae += 1./(2*((1U<alpha_sBIT)-1)); + } + else + { + that->alpha = scale; /* opaque */ + that->alpha = 1; /* Override this. */ + that->alphae = 0; /* It's exact ;-) */ + } +} + +/* Static 'end' structure: */ +static image_transform image_transform_end = +{ + "(end)", /* name */ + 1, /* enable */ + 0, /* list */ + 0, /* global_use */ + 0, /* local_use */ + 0, /* next */ + image_transform_set_end, + image_transform_mod_end, + 0 /* never called, I want it to crash if it is! */ +}; + +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +static void +transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id, + PNG_CONST image_transform *transform_list) +{ + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/); + + /* Parameter fields */ + dp->pm = pm; + dp->transform_list = transform_list; + + /* Local variable fields */ + dp->output_colour_type = 255; /* invalid */ + dp->output_bit_depth = 255; /* invalid */ +} + +static void +transform_info_imp(transform_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* Now set the list of transforms. */ + dp->transform_list->set(dp->transform_list, dp, pp, pi); + + /* Update the info structure for these transforms: */ + png_read_update_info(pp, pi); + + /* And get the output information into the standard_display */ + standard_info_part2(&dp->this, pp, pi, 1/*images*/); + + /* Plus the extra stuff we need for the transform tests: */ + dp->output_colour_type = png_get_color_type(pp, pi); + dp->output_bit_depth = png_get_bit_depth(pp, pi); + + /* Validate the combination of colour type and bit depth that we are getting + * out of libpng; the semantics of something not in the PNG spec are, at + * best, unclear. + */ + switch (dp->output_colour_type) + { + case PNG_COLOR_TYPE_PALETTE: + if (dp->output_bit_depth > 8) goto error; + /*FALL THROUGH*/ + case PNG_COLOR_TYPE_GRAY: + if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 || + dp->output_bit_depth == 4) + break; + /*FALL THROUGH*/ + default: + if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16) + break; + /*FALL THROUGH*/ + error: + { + char message[128]; + size_t pos; + + pos = safecat(message, sizeof message, 0, + "invalid final bit depth: colour type("); + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, ") with bit depth: "); + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + + png_error(pp, message); + } + } + + /* Use a test pixel to check that the output agrees with what we expect - + * this avoids running the whole test if the output is unexpected. + */ + { + image_pixel test_pixel; + + memset(&test_pixel, 0, sizeof test_pixel); + test_pixel.colour_type = dp->this.colour_type; /* input */ + test_pixel.bit_depth = dp->this.bit_depth; + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) + test_pixel.sample_depth = 8; + else + test_pixel.sample_depth = test_pixel.bit_depth; + /* Don't need sBIT here */ + test_pixel.have_tRNS = dp->this.is_transparent; + + dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); + + if (test_pixel.colour_type != dp->output_colour_type) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "colour type "); + + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.colour_type); + + png_error(pp, message); + } + + if (test_pixel.bit_depth != dp->output_bit_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "bit depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); + + png_error(pp, message); + } + + /* If both bit depth and colour type are correct check the sample depth. + * I believe these are both internal errors. + */ + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) + { + if (test_pixel.sample_depth != 8) /* oops - internal error! */ + png_error(pp, "pngvalid: internal: palette sample depth not 8"); + } + else if (test_pixel.sample_depth != dp->output_bit_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, + "internal: sample depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth); + + png_error(pp, message); + } + } +} + +static void +transform_info(png_structp pp, png_infop pi) +{ + transform_info_imp(png_get_progressive_ptr(pp), pp, 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) +{ + /* 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.) + */ + unsigned int max = (1U<= in_min && out <= in_max)) + { + char message[256]; + size_t pos; + + pos = safecat(message, sizeof message, 0, name); + pos = safecat(message, sizeof message, pos, " output value error: rgba("); + pos = safecatn(message, sizeof message, pos, r); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, g); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, b); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, a); + pos = safecat(message, sizeof message, pos, "): "); + pos = safecatn(message, sizeof message, pos, out); + pos = safecat(message, sizeof message, pos, " expected: "); + pos = safecatn(message, sizeof message, pos, in_digitized); + pos = safecat(message, sizeof message, pos, " ("); + pos = safecatd(message, sizeof message, pos, (in-err)*max, 3); + pos = safecat(message, sizeof message, pos, ".."); + pos = safecatd(message, sizeof message, pos, (in+err)*max, 3); + pos = safecat(message, sizeof message, pos, ")"); + + png_error(pp, message); + } +} + +static void +transform_image_validate(transform_display *dp, png_structp pp, png_infop pi, + png_const_bytep pRow) +{ + /* Constants for the loop below: */ + 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 == + PNG_COLOR_TYPE_PALETTE ? 8 : out_bd); + PNG_CONST png_byte red_sBIT = dp->this.red_sBIT; + PNG_CONST png_byte green_sBIT = dp->this.green_sBIT; + 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; + + standard_palette out_palette; + png_uint_32 y; + + UNUSED(pi) + + /* 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); + else + memset(out_palette, 0x5e, sizeof out_palette); + + for (y=0; ythis.palette); + + in_pixel.red_sBIT = red_sBIT; + in_pixel.green_sBIT = green_sBIT; + in_pixel.blue_sBIT = blue_sBIT; + in_pixel.alpha_sBIT = alpha_sBIT; + in_pixel.have_tRNS = have_tRNS; + + /* For error detection, below. */ + r = in_pixel.red; + g = in_pixel.green; + b = in_pixel.blue; + a = in_pixel.alpha; + + dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp); + + /* Read the output pixel and compare it to what we got, we don't + * use the error field here, so no need to update sBIT. + */ + image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette); + + /* We don't expect changes to the index here even if the bit depth is + * changed. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE && + out_ct == PNG_COLOR_TYPE_PALETTE) + { + if (in_pixel.palette_index != out_pixel.palette_index) + png_error(pp, "unexpected transformed palette index"); + } + + /* Check the colours for palette images too - in fact the palette could + * be separately verified itself in most cases. + */ + 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"); + + 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"); + + 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"); + + 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"); + } /* pixel (x) loop */ + } /* row (y) loop */ + + /* Record that something was actually checked to avoid a false positive. */ + dp->this.ps->validated = 1; +} + +static void +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); +} + +/* A single test run. */ +static void +transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, + PNG_CONST image_transform* transform_listIn, PNG_CONST char *name) +{ + transform_display d; + context(&pmIn->this, fault); + + transform_display_init(&d, pmIn, idIn, transform_listIn); + + Try + { + png_structp pp; + png_infop pi; + + /* Get a png_struct for writing the image. */ + pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); + +# if 0 + /* Logging (debugging only) */ + { + char buffer[256]; + + (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0, + "running test"); + + fprintf(stderr, "%s\n", buffer); + } +# endif + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, transform_info, progressive_row, + transform_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* 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); + + transform_image_validate(&d, pp, pi, d.this.ps->image); + } + + modifier_reset(d.pm); + } + + Catch(fault) + modifier_reset((png_modifier*)fault); +} + +/* The transforms: */ +#define ITSTRUCT(name) image_transform_##name +#define IT(name,prev)\ +static image_transform ITSTRUCT(name) =\ +{\ + #name,\ + 1, /*enable*/\ + &ITSTRUCT(prev), /*list*/\ + 0, /*global_use*/\ + 0, /*local_use*/\ + 0, /*next*/\ + image_transform_png_set_##name##_set,\ + image_transform_png_set_##name##_mod,\ + image_transform_png_set_##name##_add\ +} + +/* To save code: */ +static int +image_transform_default_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return 1; +} + +/* png_set_palette_to_rgb */ +static void +image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_palette_to_rgb(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +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); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_palette_to_rgb_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type == PNG_COLOR_TYPE_PALETTE; +} + +IT(palette_to_rgb, end); + + +/* png_set_tRNS_to_alpha */ +static void +image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_tRNS_to_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* LIBPNG BUG: this always forces palette images to RGB. */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that, &display->this); + + /* This effectively does an 'expand' only if there is some transparency to + * covert to an alpha channel. + */ + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */ + else + { + if (that->bit_depth < 8) + that->bit_depth =8; + if (that->sample_depth < 8) + that->sample_depth = 8; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_tRNS_to_alpha_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* We don't know yet whether there will be a tRNS chunk, but we know that + * this transformation should do nothing if there already is an alpha + * channel. + */ + return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(tRNS_to_alpha,palette_to_rgb); + +/* png_set_gray_to_rgb */ +static void +image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_gray_to_rgb(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* NOTE: we can actually pend the tRNS processing at this point because we + * can correctly recognize the original pixel value even though we have + * mapped the one gray channel to the three RGB ones, but in fact libpng + * doesn't do this, so we don't either. + */ + if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + /* Simply expand the bit depth and alter the colour type as required. */ + if (that->colour_type == PNG_COLOR_TYPE_GRAY) + { + /* RGB images have a bit depth at least equal to '8' */ + if (that->bit_depth < 8) + that->sample_depth = that->bit_depth = 8; + + /* And just changing the colour type works here because the green and blue + * channels are being maintained in lock-step with the red/gray: + */ + that->colour_type = PNG_COLOR_TYPE_RGB; + } + + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_gray_to_rgb_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) == 0; +} + +IT(gray_to_rgb,tRNS_to_alpha); + +/* png_set_expand */ +static void +image_transform_png_set_expand_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_expand(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* 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); + else if (that->bit_depth < 8) /* grayscale */ + that->sample_depth = that->bit_depth = 8; + + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_expand_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit + * depth is at least 8 already. + */ + return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(expand,gray_to_rgb); + +/* png_set_expand_gray_1_2_4_to_8 + * LIBPNG BUG: this just does an 'expand' + */ +static void +image_transform_png_set_expand_gray_1_2_4_to_8_set( + PNG_CONST image_transform *this, transform_display *that, png_structp pp, + png_infop pi) +{ + png_set_expand_gray_1_2_4_to_8(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_gray_1_2_4_to_8_mod( + PNG_CONST image_transform *this, image_pixel *that, png_structp pp, + PNG_CONST transform_display *display) +{ + image_transform_png_set_expand_mod(this, that, pp, display); +} + +static int +image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + return image_transform_png_set_expand_add(this, that, colour_type, + bit_depth); +} + +IT(expand_gray_1_2_4_to_8, expand); +/* 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, &display->this); + + 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, expand_gray_1_2_4_to_8); + +/* png_set_strip_16 */ +static void +image_transform_png_set_strip_16_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_16(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_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; + +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + /* The strip 16 algoirithm drops the low 8 bits rather than calculating + * 1/257, so we need to adjust the permitted errors appropriately: + */ + { + PNG_CONST double d = (255-128.5)/65535; + that->rede += d; + that->greene += d; + that->bluee += d; + that->alphae += d; + } +# endif + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_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(strip_16, expand_16); + +/* png_set_strip_alpha */ +static void +image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + + that->have_tRNS = 0; + that->alphaf = 1; + that->alphae = 0; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_alpha_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; +} + +IT(strip_alpha,strip_16); + +/* 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) + * png_get_rgb_to_gray_status + * + * At present the APIs are simply tested using the 16.16 fixed point conversion + * values known to be used inside libpng: + * + * red: 6968 + * green: 23434 + * blue: 2366 + * + * NOTE: this currently ignores the gamma because no gamma is being set, the + * tests on gamma need to happen in the gamma test set. + */ +static void +image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + PNG_CONST int error_action = 1; /* no error, no defines in png.h */ + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_rgb_to_gray(pp, error_action, -1, -1); +# else + png_set_rgb_to_gray_fixed(pp, error_action, -1, -1); +# endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + 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 now has RGB channels... */ + that->bluef = that->greenf = that->redf = (that->redf * 6968 + + that->greenf * 23434 + that->bluef * 2366) / 32768; + that->bluee = that->greene = that->rede = (that->rede * 6968 + + that->greene * 23434 + that->bluee * 2366) / 32768 * + (1 + DBL_EPSILON * 6); + + /* The sBIT is the minium of the three colour channel sBITs. */ + if (that->red_sBIT > that->green_sBIT) + that->red_sBIT = that->green_sBIT; + if (that->red_sBIT > that->blue_sBIT) + that->red_sBIT = that->blue_sBIT; + that->blue_sBIT = that->green_sBIT = that->red_sBIT; + + /* And zap the colour bit in the type: */ + if (that->colour_type == PNG_COLOR_TYPE_RGB) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_rgb_to_gray_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) != 0; +} + +IT(rgb_to_gray,strip_alpha); + +/* 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, + * int background_gamma_code, int need_expand, + * png_fixed_point background_gamma) + * + * As with rgb_to_gray this ignores the gamma. +*/ +static void +image_transform_png_set_background_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + 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. + */ + back.index = 255; /* Should not be used */ + back.gray = back.blue = back.green = back.red = + (png_uint_16)((1U << that->this.bit_depth) >> 1); + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); +# else + png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); +# endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_background_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* Check for tRNS first: */ + if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE) + image_pixel_add_alpha(that, &display->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); + + /* 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; + } + + else + { + 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 * + DBL_EPSILON; + that->bluef = that->bluef * that->alphaf + component; + that->bluee = that->bluee * that->alphaf + that->bluef * 3 * + DBL_EPSILON; + } + + /* Remove the alpha type and set the alpha. */ + that->alphaf = 1; + that->alphae = 0; + + if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + } + + this->next->mod(this->next, that, pp, display); +} + +#define image_transform_png_set_background_add image_transform_default_add + +IT(background,rgb_to_gray); + +static image_transform *PNG_CONST image_transform_first = &ITSTRUCT(background); + +static void +transform_enable(PNG_CONST char *name) +{ + /* Everything starts out enabled, so if we see an 'enable' disabled + * everything else the first time round. + */ + static int all_disabled = 0; + int found_it = 0; + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 1; + found_it = 1; + } + else if (!all_disabled) + list->enable = 0; + + list = list->list; + } + + all_disabled = 1; + + if (!found_it) + { + fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", + name); + exit(1); + } +} + +static void +transform_disable(PNG_CONST char *name) +{ + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 0; + return; + } + + list = list->list; + } + + fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", + name); + exit(1); +} + +static void +image_transform_reset_count(void) +{ + image_transform *next = image_transform_first; + int count = 0; + + while (next != &image_transform_end) + { + next->local_use = 0; + next->next = 0; + next = next->list; + ++count; + } + + /* This can only happen if we every have more than 32 transforms (excluding + * the end) in the list. + */ + if (count > 32) abort(); +} + +static int +image_transform_test_counter(png_uint_32 counter, unsigned int max) +{ + /* Test the list to see if there is any point contining, given a current + * counter and a 'max' value. + */ + image_transform *next = image_transform_first; + + while (next != &image_transform_end) + { + /* For max 0 or 1 continue until the counter overflows: */ + counter >>= 1; + + /* Continue if any entry hasn't reacked the max. */ + if (max > 1 && next->local_use < max) + return 1; + next = next->list; + } + + return max <= 1 && counter == 0; +} + +static png_uint_32 +image_transform_add(PNG_CONST image_transform **this, unsigned int max, + png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos, + png_byte colour_type, png_byte bit_depth) +{ + for (;;) /* until we manage to add something */ + { + png_uint_32 mask; + image_transform *list; + + /* Find the next counter value, if the counter is zero this is the start + * of the list. This routine always returns the current counter (not the + * next) so it returns 0 at the end and expects 0 at the beginning. + */ + if (counter == 0) /* first time */ + { + image_transform_reset_count(); + if (max <= 1) + counter = 1; + else + counter = random_32(); + } + else /* advance the counter */ + { + switch (max) + { + case 0: ++counter; break; + case 1: counter <<= 1; break; + default: counter = random_32(); break; + } + } + + /* Now add all these items, if possible */ + *this = &image_transform_end; + list = image_transform_first; + mask = 1; + + /* Go through the whole list adding anything that the counter selects: */ + while (list != &image_transform_end) + { + if ((counter & mask) != 0 && list->enable && + (max == 0 || list->local_use < max)) + { + /* Candidate to add: */ + if (list->add(list, this, colour_type, bit_depth) || max == 0) + { + /* Added, so add to the name too. */ + *pos = safecat(name, sizeof_name, *pos, " +"); + *pos = safecat(name, sizeof_name, *pos, list->name); + } + + else + { + /* Not useful and max>0, so remvoe it from *this: */ + *this = list->next; + list->next = 0; + + /* And, since we know it isn't useful, stop it being added again + * in this run: + */ + list->local_use = max; + } + } + + mask <<= 1; + list = list->list; + } + + /* Now if anything was added we have something to do. */ + if (*this != &image_transform_end) + return counter; + + /* Nothing added, but was there anything in there to add? */ + if (!image_transform_test_counter(counter, max)) + return 0; + } +} + +#ifdef THIS_IS_THE_PROFORMA +static void +image_transform_png_set_@_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_@(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_@_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_@_add(image_transform *this, + PNG_CONST image_transform **that, char *name, size_t sizeof_name, + size_t *pos, png_byte colour_type, png_byte bit_depth) +{ + this->next = *that; + *that = this; + + *pos = safecat(name, sizeof_name, *pos, " +@"); + + return 1; +} + +IT(@); +#endif + +/* png_set_quantize(png_structp, png_colorp palette, int num_palette, + * int maximum_colors, png_const_uint_16p histogram, int full_quantize) + * + * Very difficult to validate this! + */ +/*NOTE: TBD NYI */ + +/* The data layout transforms are handled by swapping our own channel data, + * necessarily these need to happen at the end of the transform list because the + * semantic of the channels changes after these are executed. Some of these, + * like set_shift and set_packing, can't be done at present because they change + * the layout of the data at the sub-sample level so sample() won't get the + * right answer. + */ +/* png_set_invert_alpha */ +/*NOTE: TBD NYI */ + +/* png_set_bgr */ +/*NOTE: TBD NYI */ + +/* png_set_swap_alpha */ +/*NOTE: TBD NYI */ + +/* png_set_swap */ +/*NOTE: TBD NYI */ + +/* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */ +/*NOTE: TBD NYI */ + +/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */ +/*NOTE: TBD NYI */ + +/* png_set_packing */ +/*NOTE: TBD NYI */ + +/* png_set_packswap */ +/*NOTE: TBD NYI */ + +/* png_set_invert_mono */ +/*NOTE: TBD NYI */ + +/* 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) +{ + for (; bdlo <= bdhi; ++bdlo) + { + PNG_CONST png_byte bit_depth = DEPTH(bdlo); + png_uint_32 counter = 0; + size_t base_pos; + char name[64]; + + base_pos = safecat(name, sizeof name, 0, "transform:"); + + for (;;) + { + 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); + + 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); + + if (fail(pm)) + return 0; + } + } + + 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; +} + + +/********************************* GAMMA TESTS ********************************/ +/* Gamma test images. */ +typedef struct gamma_modification +{ + png_modification this; + png_fixed_point gamma; +} gamma_modification; + +static int +gamma_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* This simply dumps the given gamma value into the buffer. */ + png_save_uint_32(pm->buffer, 4); + png_save_uint_32(pm->buffer+4, CHUNK_gAMA); + png_save_uint_32(pm->buffer+8, ((gamma_modification*)me)->gamma); + return 1; +} + +static void +gamma_modification_init(gamma_modification *me, png_modifier *pm, double gammad) +{ + double g; + + modification_init(&me->this); + me->this.chunk = CHUNK_gAMA; + me->this.modify_fn = gamma_modify; + me->this.add = CHUNK_PLTE; + g = floor(gammad * 100000 + .5); + me->gamma = (png_fixed_point)g; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct srgb_modification +{ + png_modification this; + png_byte intent; +} srgb_modification; + +static int +srgb_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* As above, ignore add and just make a new chunk */ + png_save_uint_32(pm->buffer, 1); + png_save_uint_32(pm->buffer+4, CHUNK_sRGB); + pm->buffer[8] = ((srgb_modification*)me)->intent; + return 1; +} + +static void +srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + + if (intent <= 3) /* if valid, else *delete* sRGB chunks */ + { + me->this.modify_fn = srgb_modify; + me->this.add = CHUNK_PLTE; + me->intent = intent; + } + + else + { + me->this.modify_fn = 0; + me->this.add = 0; + me->intent = 0; + } + + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct sbit_modification +{ + png_modification this; + png_byte sbit; +} sbit_modification; + +static int +sbit_modify(png_modifier *pm, png_modification *me, int add) +{ + png_byte sbit = ((sbit_modification*)me)->sbit; + if (pm->bit_depth > sbit) + { + int cb = 0; + switch (pm->colour_type) + { + case 0: + cb = 1; + break; + + case 2: + case 3: + cb = 3; + break; + + case 4: + cb = 2; + break; + + case 6: + cb = 4; + break; + + default: + png_error(pm->this.pread, + "unexpected colour type in sBIT modification"); + } + + png_save_uint_32(pm->buffer, cb); + png_save_uint_32(pm->buffer+4, CHUNK_sBIT); + + while (cb > 0) + (pm->buffer+8)[--cb] = sbit; + + return 1; + } + else if (!add) + { + /* Remove the sBIT chunk */ + pm->buffer_count = pm->buffer_position = 0; + return 1; + } + else + return 0; /* do nothing */ +} + +static void +sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + me->this.modify_fn = sbit_modify; + me->this.add = CHUNK_PLTE; + me->sbit = sbit; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +typedef struct gamma_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + double file_gamma; + double screen_gamma; + png_byte sbit; + int threshold_test; + PNG_CONST char* name; + int speed; + int use_input_precision; + int strip16; + + /* Local variables */ + double maxerrout; + double maxerrpc; + double maxerrabs; +} gamma_display; + +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) +{ + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/); + + /* Parameter fields */ + dp->pm = pm; + dp->file_gamma = file_gamma; + dp->screen_gamma = screen_gamma; + dp->sbit = sbit; + dp->threshold_test = threshold_test; + dp->speed = speed; + dp->use_input_precision = use_input_precision; + dp->strip16 = strip16; + + /* Local variable fields */ + dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; +} + +static void +gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* If requested strip 16 to 8 bits - this is handled automagically below + * because the output bit depth is read from the library. Note that there + * 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); +# else + png_error(pp, "strip16 (16 to 8 bit conversion) not supported"); +# endif + + png_read_update_info(pp, pi); + + /* Now we may get a different cbRow: */ + standard_info_part2(&dp->this, pp, pi, 1 /*images*/); +} + +static void +gamma_info(png_structp pp, png_infop pi) +{ + gamma_info_imp(png_get_progressive_ptr(pp), pp, pi); +} + +static void +gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, + png_const_bytep pRow) +{ + /* 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_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 = png_get_color_type(pp, pi); + PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi); + PNG_CONST unsigned int outmax = (1U<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 + * the output (screen) gamma and thirdly the output file encoding. + * + * Since this API receives the screen and file gamma in double + * precision it is possible to calculate an exact answer given an input + * pixel value. Therefore we assume that the *input* value is exact - + * sample/maxsample - calculate the corresponding gamma corrected + * output to the limits of double precision arithmetic and compare with + * what libpng returns. + * + * Since the library must quantize the output to 8 or 16 bits there is + * a fundamental limit on the accuracy of the output of +/-.5 - this + * quantization limit is included in addition to the other limits + * specified by the paramaters to the API. (Effectively, add .5 + * everywhere.) + * + * The behavior of the 'sbit' paramter is defined by section 12.5 + * (sample depth scaling) of the PNG spec. That section forces the + * decoder to assume that the PNG values have been scaled if sBIT is + * present: + * + * png-sample = floor( input-sample * (max-out/max-in) + .5); + * + * This means that only a subset of the possible PNG values should + * appear in the input. However, the spec allows the encoder to use a + * variety of approximations to the above and doesn't require any + * restriction of the values produced. + * + * Nevertheless the spec requires that the upper 'sBIT' bits of the + * value stored in a PNG file be the original sample bits. + * Consequently the code below simply scales the top sbit bits by + * (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; + + PNG_CONST double gamma_correction = 1/(file_gamma*screen_gamma);/* Overall */ + + double maxerrout = 0, maxerrabs = 0, maxerrpc = 0; + png_uint_32 y; + + for (y=0; y> (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< 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; + + /* 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; + } + + /* 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 * maxpc; + if (tmp < maxabs) tmp = maxabs; + + /* Low bound - the minimum of the three: */ + es_lo = encoded_sample - maxout; + + if (es_lo > 0 && input_sample-tmp > 0) + { + double low_value = outmax * pow(input_sample-tmp, + 1/screen_gamma); + if (low_value < es_lo) es_lo = low_value; + } + + else + es_lo = 0; + + es_hi = encoded_sample + maxout; + + if (es_hi < outmax && input_sample+tmp < 1) + { + double high_value = outmax * pow(input_sample+tmp, + 1/screen_gamma); + if (high_value > es_hi) es_hi = high_value; + } + + 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) + { + /* 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< 0) + { + is_lo = outmax * pow(tmp, gamma_correction) - maxout; + if (is_lo < 0) is_lo = 0; + } + + else + is_lo = 0; + + tmp = (isbit + .5)/((1U< 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); + } + } + } + } + + else if (!speed && memcmp(std, pRow, cbRow) != 0) + { + char msg[64]; + + /* No transform is expected on the threshold tests. */ + sprintf(msg, "gamma: below threshold row %d changed", y); + + png_error(pp, msg); + } + } /* row (y) loop */ + + dp->maxerrout = maxerrout; + dp->maxerrabs = maxerrabs; + dp->maxerrpc = maxerrpc; + dp->this.ps->validated = 1; +} + +static void +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); +} + +/* A single test run checking a gamma transformation. + * + * maxabs: maximum absolute error as a fraction + * maxout: maximum output error in the output units + * maxpc: maximum percentage error (as a percentage) + */ +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 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) +{ + 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); + + Try + { + png_structp pp; + png_infop pi; + gamma_modification gamma_mod; + srgb_modification srgb_mod; + sbit_modification sbit_mod; + + /* Make an appropriate modifier to set the PNG file gamma to the + * given gamma value and the sBIT chunk to the given precision. + */ + 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); + + 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 + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row, + gamma_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* 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); + + gamma_image_validate(&d, pp, pi, d.this.ps->image); + } + + modifier_reset(d.pm); + + if (d.pm->log && !d.threshold_test && !d.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.maxerrout, d.maxerrabs, 100*d.maxerrpc); + + /* Log the summary values too. */ + if (d.this.colour_type == 0 || d.this.colour_type == 4) + { + switch (d.this.bit_depth) + { + case 1: + break; + + case 2: + if (d.maxerrout > d.pm->error_gray_2) + d.pm->error_gray_2 = d.maxerrout; + + break; + + case 4: + if (d.maxerrout > d.pm->error_gray_4) + d.pm->error_gray_4 = d.maxerrout; + + break; + + case 8: + if (d.maxerrout > d.pm->error_gray_8) + d.pm->error_gray_8 = d.maxerrout; + + break; + + case 16: + if (d.maxerrout > d.pm->error_gray_16) + d.pm->error_gray_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 1)"); + } + } + + else if (d.this.colour_type == 2 || d.this.colour_type == 6) + { + switch (d.this.bit_depth) + { + case 8: + + if (d.maxerrout > d.pm->error_color_8) + d.pm->error_color_8 = d.maxerrout; + + break; + + case 16: + + if (d.maxerrout > d.pm->error_color_16) + d.pm->error_color_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 2)"); + } + } + } + + Catch(fault) + modifier_reset((png_modifier*)fault); +} + +static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, + png_byte bit_depth, int interlace_type, double file_gamma, + double screen_gamma) +{ + size_t pos = 0; + char name[64]; + pos = safecat(name, sizeof name, pos, "threshold "); + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + 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*/); +} + +static void +perform_gamma_threshold_tests(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + + while (next_format(&colour_type, &bit_depth)) + { + double test_gamma = 1.0; + while (test_gamma >= .4) + { + /* There's little point testing the interlacing vs non-interlacing, + * but this can be set from the command line. + */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + test_gamma, 1/test_gamma); + test_gamma *= .95; + } + + /* And a special test for sRGB */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + .45455, 2.2); + + if (fail(pm)) + return; + } +} + +static void gamma_transform_test(png_modifier *pm, + PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, + 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) +{ + size_t pos = 0; + char name[64]; + + if (sbit != bit_depth) + { + pos = safecat(name, sizeof name, pos, "sbit("); + pos = safecatn(name, sizeof name, pos, sbit); + pos = safecat(name, sizeof name, pos, ") "); + } + + else + pos = safecat(name, sizeof name, pos, "gamma "); + + if (strip16) + 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); +} + +static void perform_gamma_transform_tests(png_modifier *pm, int speed) +{ + png_byte colour_type = 0; + png_byte bit_depth = 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) + { + unsigned int i, j; + + for (i=0; ingammas; ++i) for (j=0; jngammas; ++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*/); + + if (fail(pm)) + return; + } + } +} + +static void perform_gamma_sbit_tests(png_modifier *pm, int speed) +{ + 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 (sbit=pm->sbitlow; sbit<(1<ngammas; ++i) + { + for (j=0; jngammas; ++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; + + 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*/); + + 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*/); + + if (fail(pm)) + return; + + 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*/); + + if (fail(pm)) + return; +#endif + } + } + } + } +} + +/* Note that this requires a 16 bit source image but produces 8 bit output, so + * we only need the 16bit write support. + */ +#ifdef PNG_READ_16_TO_8_SUPPORTED +static void perform_gamma_strip16_tests(png_modifier *pm, int speed) +{ +# ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +# endif + /* Include the alpha cases here. Note that sbit matches the internal value + * used by the library - otherwise we will get spurious errors from the + * internal sbit style approximation. + * + * The threshold test is here because otherwise the 16 to 8 conversion will + * proceed *without* gamma correction, and the tests above will fail (but not + * by much) - this could be fixed, it only appears with the -g option. + */ + unsigned int i, j; + for (i=0; ingammas; ++i) + { + for (j=0; jngammas; ++j) + { + 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*/); + + 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*/); + + 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*/); + + 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*/); + + if (fail(pm)) + return; + } + } + } +} +#endif /* 16 to 8 bit conversion */ + +static void +perform_gamma_test(png_modifier *pm, int speed, int summary) +{ + /* First some arbitrary no-transform tests: */ + if (!speed && pm->test_gamma_threshold) + { + perform_gamma_threshold_tests(pm); + + if (fail(pm)) + return; + } + + /* Now some real transforms. */ + if (pm->test_gamma_transform) + { + perform_gamma_transform_tests(pm, speed); + + if (summary) + { + printf("Gamma correction error summary\n\n"); + printf("The printed value is the maximum error in the pixel values\n"); + printf("calculated by the libpng gamma correction code. The error\n"); + printf("is calculated as the difference between the output pixel\n"); + printf("value (always an integer) and the ideal value from the\n"); + printf("libpng specification (typically not an integer).\n\n"); + + printf("Expect this value to be less than .5 for 8 bit formats,\n"); + printf("less than 1 for formats with fewer than 8 bits and a small\n"); + printf("number (typically less than 5) for the 16 bit formats.\n"); + 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 + } + } + + /* 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); + + 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 + } + } + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (pm->test_gamma_strip16) + { + /* 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); + + if (summary) + { + printf("Gamma correction with 16 to 8 bit reduction:\n"); + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); + } + } +#endif +} + +/* INTERLACE MACRO VALIDATION */ +/* This is copied verbatim from the specification, it is simply the pass + * number in which each pixel in each 8x8 tile appears. The array must + * be indexed adam7[y][x] and notice that the pass numbers are based at + * 1, not 0 - the base libpng uses. + */ +static PNG_CONST +png_byte adam7[8][8] = +{ + { 1,6,4,6,2,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 }, + { 3,6,4,6,3,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 } +}; + +/* This routine validates all the interlace support macros in png.h for + * a variety of valid PNG widths and heights. It uses a number of similarly + * named internal routines that feed off the above array. + */ +static png_uint_32 +png_pass_start_row(int pass) +{ + int x, y; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return y; + return 0xf; +} + +static png_uint_32 +png_pass_start_col(int pass) +{ + int x, y; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return x; + return 0xf; +} + +static int +png_pass_row_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = y; + else if (base == y) + {} + else if (inc == y-base) + base=y; + else if (inc == 8) + inc = y-base, base=y; + else if (inc != y-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static int +png_pass_col_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = x; + else if (base == x) + {} + else if (inc == x-base) + base=x; + else if (inc == 8) + inc = x-base, base=x; + else if (inc != x-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 1: return 0; /* pass 7 has all the columns */ +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static png_uint_32 +png_row_from_pass_row(png_uint_32 yIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return yIn * 8; +case 1: return yIn * 8; +case 2: return yIn * 8 + 4; +case 3: return yIn * 4; +case 4: return yIn * 4 + 2; +case 5: return yIn * 2; +case 6: return yIn * 2 + 1; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static png_uint_32 +png_col_from_pass_col(png_uint_32 xIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return xIn * 8; +case 1: return xIn * 8 + 4; +case 2: return xIn * 4; +case 3: return xIn * 4 + 2; +case 4: return xIn * 2; +case 5: return xIn * 2 + 1; +case 6: return xIn; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static int +png_row_in_interlace_pass(png_uint_32 y, int pass) +{ + /* Is row 'y' in pass 'pass'? */ + int x; + y &= 7; + ++pass; + for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static int +png_col_in_interlace_pass(png_uint_32 x, int pass) +{ + /* Is column 'x' in pass 'pass'? */ + int y; + x &= 7; + ++pass; + for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static png_uint_32 +png_pass_rows(png_uint_32 height, int pass) +{ + png_uint_32 tiles = height>>3; + png_uint_32 rows = 0; + unsigned int x, y; + + height &= 7; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + rows += tiles; + if (y < height) ++rows; + break; /* i.e. break the 'x', column, loop. */ + } + + return rows; +} + +static png_uint_32 +png_pass_cols(png_uint_32 width, int pass) +{ + png_uint_32 tiles = width>>3; + png_uint_32 cols = 0; + unsigned int x, y; + + width &= 7; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + cols += tiles; + if (x < width) ++cols; + break; /* i.e. break the 'y', row, loop. */ + } + + return cols; +} + +static void +perform_interlace_macro_validation(void) +{ + /* The macros to validate, first those that depend only on pass: + * + * PNG_PASS_START_ROW(pass) + * PNG_PASS_START_COL(pass) + * PNG_PASS_ROW_SHIFT(pass) + * PNG_PASS_COL_SHIFT(pass) + */ + int pass; + + for (pass=0; pass<7; ++pass) + { + png_uint_32 m, f, v; + + m = PNG_PASS_START_ROW(pass); + f = png_pass_start_row(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_START_COL(pass); + f = png_pass_start_col(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_ROW_SHIFT(pass); + f = png_pass_row_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_COL_SHIFT(pass); + f = png_pass_col_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + /* Macros that depend on the image or sub-image height too: + * + * PNG_PASS_ROWS(height, pass) + * PNG_PASS_COLS(width, pass) + * PNG_ROW_FROM_PASS_ROW(yIn, pass) + * PNG_COL_FROM_PASS_COL(xIn, pass) + * PNG_ROW_IN_INTERLACE_PASS(y, pass) + * PNG_COL_IN_INTERLACE_PASS(x, pass) + */ + for (v=0;;) + { + /* First the base 0 stuff: */ + m = PNG_ROW_FROM_PASS_ROW(v, pass); + f = png_row_from_pass_row(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_COL_FROM_PASS_COL(v, pass); + f = png_col_from_pass_col(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_ROW_IN_INTERLACE_PASS(v, pass); + f = png_row_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_COL_IN_INTERLACE_PASS(v, pass); + f = png_col_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + /* Then the base 1 stuff: */ + ++v; + m = PNG_PASS_ROWS(v, pass); + f = png_pass_rows(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_PASS_COLS(v, pass); + f = png_pass_cols(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + /* Move to the next v - the stepping algorithm starts skipping + * values above 1024. + */ + if (v > 1024) + { + if (v == PNG_UINT_31_MAX) + break; + + v = (v << 1) ^ v; + if (v >= PNG_UINT_31_MAX) + v = PNG_UINT_31_MAX-1; + } + } + } +} + +/* main program */ +int main(int argc, PNG_CONST char **argv) +{ + volatile int summary = 1; /* Print the error summary at the end */ + + /* Create the given output file on success: */ + PNG_CONST char *volatile touch = NULL; + + /* This is an array of standard gamma values (believe it or not I've seen + * every one of these mentioned somewhere.) + * + * In the following list the most useful values are first! + */ + static double + gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; + + 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. + */ + pm.this.image = malloc(2*TRANSFORM_IMAGEMAX+1); + + 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; + } + + /* Default to error on warning: */ + pm.this.treat_warnings_as_errors = 1; + + /* Store the test gammas */ + 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 */ + + /* Some default values (set the behavior for 'make check' here). + * These values simply control the maximum error permitted in the gamma + * transformations. The practial limits for human perception are described + * below (the setting for maxpc16), however for 8 bit encodings it isn't + * possible to meet the accepted capabilities of human vision - i.e. 8 bit + * images can never be good enough, regardless of encoding. + */ + pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ + pm.maxabs8 = .00005; /* 1/20000 */ + pm.maxpc8 = .499; /* I.e., .499% fractional error */ + pm.maxout16 = .499; /* Error in *encoded* value */ + pm.maxabs16 = .00005;/* 1/20000 */ + + /* 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 + * maintain 1 in 10000 accuracy (in linear light space), which is what the + * following guarantees. It also allows significantly higher errors at + * higher 16 bit values, which is important for performance. The actual + * maximum 16 bit error is about +/-1.9 in the fixed point implementation but + * this is only allowed for values >38149 by the following: + */ + pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */ + + /* Now parse the command line options. */ + while (--argc >= 1) + { + if (strcmp(*++argv, "-v") == 0) + pm.this.verbose = 1; + + else if (strcmp(*argv, "-l") == 0) + pm.log = 1; + + else if (strcmp(*argv, "-q") == 0) + summary = pm.this.verbose = pm.log = 0; + + else if (strcmp(*argv, "-w") == 0) + pm.this.treat_warnings_as_errors = 0; + + else if (strcmp(*argv, "--speed") == 0) + pm.this.speed = 1, pm.ngammas = (sizeof gammas)/(sizeof gammas[0]), + pm.test_standard = 0; + + else if (strcmp(*argv, "--size") == 0) + pm.test_size = 1; + + else if (strcmp(*argv, "--nosize") == 0) + pm.test_size = 0; + + else if (strcmp(*argv, "--standard") == 0) + pm.test_standard = 1; + + else if (strcmp(*argv, "--nostandard") == 0) + pm.test_standard = 0; + + else if (strcmp(*argv, "--transform") == 0) + pm.test_transform = 1; + + else if (strcmp(*argv, "--notransform") == 0) + pm.test_transform = 0; + + else if (strncmp(*argv, "--transform-disable=", + sizeof "--transform-disable") == 0) + { + pm.test_transform = 1; + transform_disable(*argv + sizeof "--transform-disable"); + } + + else if (strncmp(*argv, "--transform-enable=", + sizeof "--transform-enable") == 0) + { + pm.test_transform = 1; + transform_enable(*argv + sizeof "--transform-enable"); + } + + else if (strcmp(*argv, "--gamma") == 0) + { + /* Just do two gamma tests here (2.2 and linear) for speed: */ + pm.ngammas = 2U; + pm.test_gamma_threshold = 1; + pm.test_gamma_transform = 1; + pm.test_gamma_sbit = 1; + pm.test_gamma_strip16 = 1; + } + + else if (strcmp(*argv, "--nogamma") == 0) + pm.ngammas = 0; + + else if (strcmp(*argv, "--gamma-threshold") == 0) + pm.ngammas = 2U, pm.test_gamma_threshold = 1; + + else if (strcmp(*argv, "--nogamma-threshold") == 0) + pm.test_gamma_threshold = 0; + + else if (strcmp(*argv, "--gamma-transform") == 0) + pm.ngammas = 2U, pm.test_gamma_transform = 1; + + else if (strcmp(*argv, "--nogamma-transform") == 0) + pm.test_gamma_transform = 0; + + else if (strcmp(*argv, "--gamma-sbit") == 0) + pm.ngammas = 2U, pm.test_gamma_sbit = 1; + + else if (strcmp(*argv, "--nogamma-sbit") == 0) + pm.test_gamma_sbit = 0; + + else if (strcmp(*argv, "--gamma-16-to-8") == 0) + pm.ngammas = 2U, pm.test_gamma_strip16 = 1; + + else if (strcmp(*argv, "--nogamma-16-to-8") == 0) + pm.test_gamma_strip16 = 0; + + else if (strcmp(*argv, "--all-gammas") == 0) + pm.ngammas = (sizeof gammas)/(sizeof gammas[0]); + + else if (strcmp(*argv, "--progressive-read") == 0) + pm.this.progressive = 1; + + 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 (argc >= 1 && strcmp(*argv, "--touch") == 0) + --argc, touch = *++argv; + + else if (argc >= 1 && strncmp(*argv, "--max", 4) == 0) + { + --argc; + + if (strcmp(4+*argv, "abs8") == 0) + pm.maxabs8 = atof(*++argv); + + else if (strcmp(4+*argv, "abs16") == 0) + pm.maxabs16 = atof(*++argv); + + else if (strcmp(4+*argv, "out8") == 0) + pm.maxout8 = atof(*++argv); + + else if (strcmp(4+*argv, "out16") == 0) + pm.maxout16 = atof(*++argv); + + else if (strcmp(4+*argv, "pc8") == 0) + pm.maxpc8 = atof(*++argv); + + else if (strcmp(4+*argv, "pc16") == 0) + pm.maxpc16 = atof(*++argv); + + else + { + fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); + exit(1); + } + } + + else + { + fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); + exit(1); + } + } + + /* If pngvalid is run with no arguments default to a reasonable set of the + * tests. + */ + if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 && + pm.ngammas == 0) + { + pm.test_standard = 1; + pm.test_size = 1; + pm.test_transform = 1; + pm.ngammas = 3U; + } + + 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_threshold = 1; + pm.test_gamma_transform = 1; + pm.test_gamma_sbit = 1; + pm.test_gamma_strip16 = 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; + } + + Try + { + /* Make useful base images */ + make_transform_images(&pm.this); + + /* Perform the standard and gamma tests. */ + if (pm.test_standard) + { + perform_interlace_macro_validation(); + perform_standard_test(&pm); + perform_error_test(&pm); + } + + /* Various oddly sized images: */ + if (pm.test_size) + { + make_size_images(&pm.this); + perform_size_test(&pm); + } + + /* Combinatorial transforms: */ + if (pm.test_transform) + perform_transform_test(&pm); + + if (pm.ngammas > 0) + perform_gamma_test(&pm, pm.this.speed != 0, + summary && !pm.this.speed); + } + + Catch(fault) + { + fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n"); + if (!pm.this.verbose) + { + if (pm.this.error[0] != 0) + fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error); + + fprintf(stderr, "pngvalid: run with -v to see what happened\n"); + } + exit(1); + } + + if (summary && !pm.this.speed) + { + printf("Results using %s point arithmetic %s\n", +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500 + "floating", +#else + "fixed", +#endif + (pm.this.nerrors || (pm.this.treat_warnings_as_errors && + pm.this.nwarnings)) ? "(errors)" : (pm.this.nwarnings ? + "(warnings)" : "(no errors or warnings)") + ); + 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", + (unsigned long)pm.this.read_memory_pool.max_max, + (unsigned long)pm.this.read_memory_pool.max_limit, + (unsigned long)pm.this.read_memory_pool.max_total, + (unsigned long)pm.this.write_memory_pool.max_max, + (unsigned long)pm.this.write_memory_pool.max_limit, + (unsigned long)pm.this.write_memory_pool.max_total); + } + + /* Do this here to provoke memory corruption errors in memory not directly + * allocated by libpng - not a complete test, but better than nothing. + */ + store_delete(&pm.this); + + /* Error exit if there are any errors, and maybe if there are any + * warnings. + */ + if (pm.this.nerrors || (pm.this.treat_warnings_as_errors && + pm.this.nwarnings)) + { + if (!pm.this.verbose) + fprintf(stderr, "pngvalid: %s\n", pm.this.error); + + fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors, + pm.this.nwarnings); + + exit(1); + } + + /* Success case. */ + if (touch != NULL) + { + FILE *fsuccess = fopen(touch, "wt"); + + if (fsuccess != NULL) + { + int error = 0; + fprintf(fsuccess, "PNG validation succeeded\n"); + fflush(fsuccess); + error = ferror(fsuccess); + + if (fclose(fsuccess) || error) + { + fprintf(stderr, "%s: write failed\n", touch); + exit(1); + } + } + } + + return 0; +} diff --git a/extern/libpng/include/pngwio.c b/extern/libpng/include/pngwio.c new file mode 100644 index 0000000000..95ffb3429f --- /dev/null +++ b/extern/libpng/include/pngwio.c @@ -0,0 +1,254 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.5.0 [January 6, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length); + + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +# ifdef PNG_STDIO_SUPPORTED +void PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +} +# endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED + + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; + +# else + png_ptr->output_flush_fn = output_flush_fn; +# endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +} + +#ifdef USE_FAR_KEYWORD +# ifdef _MSC_VER +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngwrite.c b/extern/libpng/include/pngwrite.c new file mode 100644 index 0000000000..9277a95162 --- /dev/null +++ b/extern/libpng/include/pngwrite.c @@ -0,0 +1,1605 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.5.1 [February 3, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED + if (info_ptr->valid & PNG_INFO_gAMA) + png_write_gAMA_fixed(png_ptr, info_ptr->gamma); +#endif +#ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_cHRM_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + png_write_cHRM_fixed(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + 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 & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + 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 & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +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_ALLOCATED) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */ + +PNG_FUNCTION(png_structp,PNGAPI +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_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + int i; + + png_debug(1, "in png_create_write_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + 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)) +#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)); +#endif + PNG_ABORT(); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#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; + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + + if (!png_cleanup_needed) + { + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_reset_filter_heuristics(png_ptr); +#endif + + return (png_ptr); +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_const_bytep row) +{ + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %u", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", + (unsigned long)png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* 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); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* 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); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + 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); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + 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)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; + +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + + default: + png_ptr->do_filter = (png_byte)filters; break; +#else + default: + png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_UP); + } + + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_AVG); + } + + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +/* Convenience reset API. */ +static void +png_reset_filter_heuristics(png_structp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + } + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +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_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = (png_uint_16) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + if (filter_costs[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_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, "Compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_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_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* 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); + + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngwtran.c b/extern/libpng/include/pngwtran.c new file mode 100644 index 0000000000..bbf4a25b92 --- /dev/null +++ b/extern/libpng/include/pngwtran.c @@ -0,0 +1,631 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FILLER_AFTER)); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + + sp++; + + if (mask > 1) + mask >>= 1; + + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + + if (mask != 0x80) + *dp = (png_byte)v; + + break; + } + + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 2; + + sp++; + } + + if (shift != 6) + *dp = (png_byte)v; + + break; + } + + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 4; + + sp++; + } + + if (shift != 4) + *dp = (png_byte)v; + + break; + } + + default: + break; + } + + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_size_t i; + png_byte mask; + png_size_t row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/extern/libpng/include/pngwutil.c b/extern/libpng/include/pngwutil.c new file mode 100644 index 0000000000..2c35785aa1 --- /dev/null +++ b/extern/libpng/include/pngwutil.c @@ -0,0 +1,2948 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.5.0 [January 6, 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.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extention.) + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} +#endif + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, chunk_name, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_const_bytep data, + png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_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 + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + png_const_bytep input; /* The uncompressed input data */ + png_size_t input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_bytep *output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_const_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* 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 + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* 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; + png_ptr->zstream.next_out = png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charpp))); + + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + /* This could be optimized to realloc() */ + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, comp->input, comp->input_len); + + return; + } + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + + png_free(png_ptr, comp->output_ptr[i]); + } + + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (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; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + PNG_IHDR; + int ret; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGB image"); + + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + png_ptr->channels = 1; + break; + + default: + png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGBA image"); + + png_ptr->channels = 4; + break; + + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + + 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"); + + if (ret == Z_MEM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + + png_error(png_ptr, "zlib failed to initialize compressor"); + } + + 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; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_const_colorp palette, + png_uint_32 num_pal) +{ + PNG_PLTE; + png_uint_32 i; + png_const_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ + PNG_IDAT; + + 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. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + 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. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + 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); + while (uncompressed_idat_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 (data[0] != z_cmf) + { + int tmp; + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ + PNG_IEND; + + png_debug(1, "in png_write_IEND"); + + png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ + PNG_gAMA; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ + PNG_sRGB; + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, + png_const_charp profile, int profile_len) +{ + PNG_iCCP; + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_const_bytep)profile ))<<24) | + ((*( (png_const_bytep)profile + 1))<<16) | + ((*( (png_const_bytep)profile + 2))<< 8) | + ((*( (png_const_bytep)profile + 3)) ); + + if (embedded_profile_len < 0) + { + png_warning(png_ptr, + "Embedded profile length in iCCP chunk is negative"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + + new_name[name_len + 1] = 0x00; + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette) +{ + PNG_sPLT; + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i = 0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) +{ + PNG_sBIT; + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ + PNG_cHRM; + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); + } +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + PNG_tRNS; + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans); + } + + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + } + + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + } + + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) +{ + PNG_bKGD; + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + + buf[0] = back->index; + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + } + + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + } + + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist) +{ + PNG_hIST; + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_const_charp ikp; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) + { + if ((png_byte)*ikp < 0x20 || + ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[40]; + + 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 + *dp = ' '; + } + + else + { + *dp = *ikp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + + else if (*kp == ' ') + { + key_len--; + kwarn = 1; + } + + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len) +{ + PNG_tEXt; + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + if (text_len) + png_write_chunk_data(png_ptr, (png_const_bytep)text, + (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + PNG_zTXt; + png_size_t key_len; + png_byte buf; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + png_free(png_ptr, new_key); + + buf = (png_byte)compression; + + /* Write compression */ + png_write_chunk_data(png_ptr, &buf, (png_size_t)1); + + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + PNG_iTXt; + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression - 2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts + */ + + png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + + /* Set the compression method */ + cbuf[1] = 0; + + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + + png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + PNG_oFFs; + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) +{ + PNG_pCAL; + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + * null terminator for the last parameter. + */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long)params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + PNG_sCAL; + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + PNG_pHYs; + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_const_timep mod_time) +{ + PNG_tIME; + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)buf_size); + + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, + (png_alloc_size_t)buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + 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; + } + } + + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + + break; + } + + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + + /* Loop through the row, only looking at the pixels that matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_size_t i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_size_t avail; + + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = 0; + avail = png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Record the number of bytes available - zlib supports at least 65535 + * bytes at one step, depending on the size of the zlib type 'uInt', the + * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). + * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. + * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a + * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called + * with smaller chunks of data. + */ + if (png_ptr->zstream.avail_in == 0) + { + if (avail > ZLIB_IO_MAX) + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + avail -= ZLIB_IO_MAX; + } + + else + { + /* So this will fit in the available uInt space: */ + png_ptr->zstream.avail_in = (uInt)avail; + avail = 0; + } + } + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* 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); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ From 1657ed4dee8363bf294d6671d164fcce708d8b06 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 8 May 2011 17:16:18 -0400 Subject: [PATCH 013/333] Add the other libpng stuff. We can remove and strip each on a case by case basis. MAC OS X builds now. Time to get the others. --- Xcode/stepmania.xcodeproj/project.pbxproj | 102 +- extern/libpng/include/CHANGES | 3297 ++++++ extern/libpng/include/CMakeLists.txt | 406 + extern/libpng/include/LICENSE | 111 + extern/libpng/include/Makefile.am | 211 + extern/libpng/include/autogen.sh | 34 + extern/libpng/include/config.guess | 1501 +++ extern/libpng/include/config.h.in | 86 + extern/libpng/include/config.sub | 1705 +++ extern/libpng/include/configure.ac | 167 + .../libpng/include/contrib/gregbook/COPYING | 340 + .../libpng/include/contrib/gregbook/LICENSE | 50 + .../include/contrib/gregbook/Makefile.mingw32 | 130 + .../include/contrib/gregbook/Makefile.sgi | 104 + .../include/contrib/gregbook/Makefile.unx | 132 + .../include/contrib/gregbook/Makefile.w32 | 113 + extern/libpng/include/contrib/gregbook/README | 186 + .../include/contrib/gregbook/makevms.com | 132 + .../libpng/include/contrib/gregbook/readpng.c | 305 + .../libpng/include/contrib/gregbook/readpng.h | 88 + .../include/contrib/gregbook/readpng2.c | 505 + .../include/contrib/gregbook/readpng2.h | 116 + .../libpng/include/contrib/gregbook/readppm.c | 179 + .../include/contrib/gregbook/rpng-win.c | 728 ++ .../libpng/include/contrib/gregbook/rpng-x.c | 904 ++ .../include/contrib/gregbook/rpng2-win.c | 1253 +++ .../libpng/include/contrib/gregbook/rpng2-x.c | 2107 ++++ .../include/contrib/gregbook/toucan.png | Bin 0 -> 12901 bytes extern/libpng/include/contrib/gregbook/wpng.c | 853 ++ .../include/contrib/gregbook/writepng.c | 400 + .../include/contrib/gregbook/writepng.h | 133 + extern/libpng/include/contrib/pngminim/README | 4 + .../include/contrib/pngminim/decoder/README | 10 + .../include/contrib/pngminim/decoder/makefile | 150 + .../contrib/pngminim/decoder/pngusr.dfa | 39 + .../include/contrib/pngminim/decoder/pngusr.h | 23 + .../include/contrib/pngminim/encoder/README | 10 + .../include/contrib/pngminim/encoder/makefile | 149 + .../contrib/pngminim/encoder/pngusr.dfa | 35 + .../include/contrib/pngminim/encoder/pngusr.h | 23 + .../include/contrib/pngminim/preader/README | 15 + .../include/contrib/pngminim/preader/makefile | 165 + .../contrib/pngminim/preader/pngusr.dfa | 40 + .../include/contrib/pngminim/preader/pngusr.h | 23 + extern/libpng/include/contrib/pngminus/README | 153 + .../include/contrib/pngminus/makefile.std | 65 + .../include/contrib/pngminus/makefile.tc3 | 38 + .../include/contrib/pngminus/makevms.com | 92 + .../include/contrib/pngminus/png2pnm.bat | 41 + .../libpng/include/contrib/pngminus/png2pnm.c | 430 + .../include/contrib/pngminus/png2pnm.sh | 42 + .../include/contrib/pngminus/pngminus.bat | 4 + .../include/contrib/pngminus/pngminus.sh | 5 + .../include/contrib/pngminus/pnm2png.bat | 41 + .../libpng/include/contrib/pngminus/pnm2png.c | 533 + .../include/contrib/pngminus/pnm2png.sh | 42 + extern/libpng/include/contrib/pngsuite/README | 102 + .../include/contrib/pngsuite/basn0g01.png | Bin 0 -> 164 bytes .../include/contrib/pngsuite/basn0g02.png | Bin 0 -> 104 bytes .../include/contrib/pngsuite/basn0g04.png | Bin 0 -> 145 bytes .../include/contrib/pngsuite/basn0g08.png | Bin 0 -> 138 bytes .../include/contrib/pngsuite/basn0g16.png | Bin 0 -> 167 bytes .../include/contrib/pngsuite/basn2c08.png | Bin 0 -> 145 bytes .../include/contrib/pngsuite/basn2c16.png | Bin 0 -> 302 bytes .../include/contrib/pngsuite/basn3p01.png | Bin 0 -> 112 bytes .../include/contrib/pngsuite/basn3p02.png | Bin 0 -> 146 bytes .../include/contrib/pngsuite/basn3p04.png | Bin 0 -> 216 bytes .../include/contrib/pngsuite/basn3p08.png | Bin 0 -> 1286 bytes .../include/contrib/pngsuite/basn4a08.png | Bin 0 -> 126 bytes .../include/contrib/pngsuite/basn4a16.png | Bin 0 -> 2206 bytes .../include/contrib/pngsuite/basn6a08.png | Bin 0 -> 184 bytes .../include/contrib/pngsuite/basn6a16.png | Bin 0 -> 3435 bytes .../include/contrib/pngsuite/ftbbn1g04.png | Bin 0 -> 429 bytes .../include/contrib/pngsuite/ftbbn2c16.png | Bin 0 -> 2041 bytes .../include/contrib/pngsuite/ftbbn3p08.png | Bin 0 -> 1499 bytes .../include/contrib/pngsuite/ftbgn2c16.png | Bin 0 -> 2041 bytes .../include/contrib/pngsuite/ftbgn3p08.png | Bin 0 -> 1499 bytes .../include/contrib/pngsuite/ftbrn2c08.png | Bin 0 -> 1633 bytes .../include/contrib/pngsuite/ftbwn1g16.png | Bin 0 -> 1313 bytes .../include/contrib/pngsuite/ftbwn3p08.png | Bin 0 -> 1496 bytes .../include/contrib/pngsuite/ftbyn3p08.png | Bin 0 -> 1499 bytes .../include/contrib/pngsuite/ftp0n1g08.png | Bin 0 -> 719 bytes .../include/contrib/pngsuite/ftp0n2c08.png | Bin 0 -> 1594 bytes .../include/contrib/pngsuite/ftp0n3p08.png | Bin 0 -> 1476 bytes .../include/contrib/pngsuite/ftp1n3p08.png | Bin 0 -> 1483 bytes .../libpng/include/contrib/visupng/PngFile.c | 442 + .../libpng/include/contrib/visupng/PngFile.h | 30 + .../libpng/include/contrib/visupng/README.txt | 61 + .../include/contrib/visupng/VisualPng.c | 964 ++ .../include/contrib/visupng/VisualPng.dsp | 147 + .../include/contrib/visupng/VisualPng.dsw | 29 + .../include/contrib/visupng/VisualPng.ico | Bin 0 -> 766 bytes .../include/contrib/visupng/VisualPng.png | Bin 0 -> 208 bytes .../include/contrib/visupng/VisualPng.rc | 152 + .../libpng/include/contrib/visupng/cexcept.h | 248 + .../libpng/include/contrib/visupng/resource.h | 23 + extern/libpng/include/depcomp | 630 ++ extern/libpng/include/example.c | 843 ++ extern/libpng/include/libpng-manual.txt | 4214 +++++++ extern/libpng/include/libpng.3 | 5461 ++++++++++ extern/libpng/include/libpng.pc.in | 11 + extern/libpng/include/libpngpf.3 | 30 + extern/libpng/include/ltmain.sh | 9636 +++++++++++++++++ extern/libpng/include/missing | 376 + extern/libpng/include/png.5 | 74 + extern/libpng/include/pngbar.jpg | Bin 0 -> 2498 bytes extern/libpng/include/pngbar.png | Bin 0 -> 2399 bytes extern/libpng/include/pnglibconf.h | 181 + .../include/projects/visualc71/PRJ0041.mak | 21 + .../include/projects/visualc71/README.txt | 58 + .../projects/visualc71/README_zlib.txt | 44 + .../include/projects/visualc71/libpng.sln | 60 + .../include/projects/visualc71/libpng.vcproj | 419 + .../include/projects/visualc71/pngtest.vcproj | 267 + .../include/projects/visualc71/zlib.vcproj | 391 + .../projects/vstudio/libpng/libpng.vcxproj | 233 + .../vstudio/pnglibconf/pnglibconf.vcxproj | 60 + .../projects/vstudio/pngtest/pngtest.vcxproj | 219 + .../vstudio/pngvalid/pngvalid.vcxproj | 219 + .../include/projects/vstudio/readme.txt | 64 + .../include/projects/vstudio/vstudio.sln | 79 + .../include/projects/vstudio/zlib.props | 30 + .../projects/vstudio/zlib/zlib.vcxproj | 174 + extern/libpng/include/scripts/README.txt | 77 + extern/libpng/include/scripts/SCOPTIONS.ppc | 7 + extern/libpng/include/scripts/checksym.awk | 161 + extern/libpng/include/scripts/chkfmt | 137 + extern/libpng/include/scripts/def.dfn | 38 + extern/libpng/include/scripts/descrip.mms | 52 + .../include/scripts/libpng-config-body.in | 96 + .../include/scripts/libpng-config-head.in | 24 + extern/libpng/include/scripts/libpng.pc.in | 10 + extern/libpng/include/scripts/list | 23 + extern/libpng/include/scripts/makefile.32sunu | 241 + extern/libpng/include/scripts/makefile.64sunu | 241 + extern/libpng/include/scripts/makefile.acorn | 57 + extern/libpng/include/scripts/makefile.aix | 121 + extern/libpng/include/scripts/makefile.amiga | 56 + extern/libpng/include/scripts/makefile.atari | 63 + extern/libpng/include/scripts/makefile.bc32 | 151 + extern/libpng/include/scripts/makefile.beos | 215 + extern/libpng/include/scripts/makefile.bor | 161 + extern/libpng/include/scripts/makefile.cegcc | 116 + extern/libpng/include/scripts/makefile.darwin | 219 + extern/libpng/include/scripts/makefile.dec | 202 + extern/libpng/include/scripts/makefile.dj2 | 62 + extern/libpng/include/scripts/makefile.elf | 263 + .../libpng/include/scripts/makefile.freebsd | 53 + extern/libpng/include/scripts/makefile.gcc | 87 + extern/libpng/include/scripts/makefile.hp64 | 224 + extern/libpng/include/scripts/makefile.hpgcc | 230 + extern/libpng/include/scripts/makefile.hpux | 221 + extern/libpng/include/scripts/makefile.ibmc | 82 + extern/libpng/include/scripts/makefile.intel | 110 + extern/libpng/include/scripts/makefile.knr | 109 + extern/libpng/include/scripts/makefile.linux | 239 + extern/libpng/include/scripts/makefile.mips | 94 + extern/libpng/include/scripts/makefile.msc | 95 + .../libpng/include/scripts/makefile.ne12bsd | 50 + extern/libpng/include/scripts/makefile.netbsd | 50 + .../libpng/include/scripts/makefile.openbsd | 82 + extern/libpng/include/scripts/makefile.sco | 218 + extern/libpng/include/scripts/makefile.sggcc | 228 + extern/libpng/include/scripts/makefile.sgi | 229 + extern/libpng/include/scripts/makefile.so9 | 239 + .../libpng/include/scripts/makefile.solaris | 236 + .../include/scripts/makefile.solaris-x86 | 236 + extern/libpng/include/scripts/makefile.std | 123 + extern/libpng/include/scripts/makefile.sunos | 107 + extern/libpng/include/scripts/makefile.tc3 | 93 + .../libpng/include/scripts/makefile.vcwin32 | 108 + extern/libpng/include/scripts/makefile.watcom | 122 + extern/libpng/include/scripts/makevms.com | 142 + extern/libpng/include/scripts/options.awk | 734 ++ extern/libpng/include/scripts/pnglibconf.dfa | 550 + extern/libpng/include/scripts/pnglibconf.h | 181 + extern/libpng/include/scripts/pnglibconf.mak | 57 + extern/libpng/include/scripts/pngwin.rc | 112 + extern/libpng/include/scripts/smakefile.ppc | 34 + extern/libpng/include/scripts/sym.dfn | 15 + extern/libpng/include/scripts/symbols.def | 229 + extern/libpng/include/scripts/symbols.dfn | 57 + extern/libpng/include/scripts/vers.dfn | 26 + 183 files changed, 53131 insertions(+), 6 deletions(-) create mode 100644 extern/libpng/include/CHANGES create mode 100644 extern/libpng/include/CMakeLists.txt create mode 100644 extern/libpng/include/LICENSE create mode 100644 extern/libpng/include/Makefile.am create mode 100755 extern/libpng/include/autogen.sh create mode 100644 extern/libpng/include/config.guess create mode 100644 extern/libpng/include/config.h.in create mode 100644 extern/libpng/include/config.sub create mode 100644 extern/libpng/include/configure.ac create mode 100644 extern/libpng/include/contrib/gregbook/COPYING create mode 100644 extern/libpng/include/contrib/gregbook/LICENSE create mode 100644 extern/libpng/include/contrib/gregbook/Makefile.mingw32 create mode 100644 extern/libpng/include/contrib/gregbook/Makefile.sgi create mode 100644 extern/libpng/include/contrib/gregbook/Makefile.unx create mode 100644 extern/libpng/include/contrib/gregbook/Makefile.w32 create mode 100644 extern/libpng/include/contrib/gregbook/README create mode 100644 extern/libpng/include/contrib/gregbook/makevms.com create mode 100644 extern/libpng/include/contrib/gregbook/readpng.c create mode 100644 extern/libpng/include/contrib/gregbook/readpng.h create mode 100644 extern/libpng/include/contrib/gregbook/readpng2.c create mode 100644 extern/libpng/include/contrib/gregbook/readpng2.h create mode 100644 extern/libpng/include/contrib/gregbook/readppm.c create mode 100644 extern/libpng/include/contrib/gregbook/rpng-win.c create mode 100644 extern/libpng/include/contrib/gregbook/rpng-x.c create mode 100644 extern/libpng/include/contrib/gregbook/rpng2-win.c create mode 100644 extern/libpng/include/contrib/gregbook/rpng2-x.c create mode 100644 extern/libpng/include/contrib/gregbook/toucan.png create mode 100644 extern/libpng/include/contrib/gregbook/wpng.c create mode 100644 extern/libpng/include/contrib/gregbook/writepng.c create mode 100644 extern/libpng/include/contrib/gregbook/writepng.h create mode 100644 extern/libpng/include/contrib/pngminim/README create mode 100644 extern/libpng/include/contrib/pngminim/decoder/README create mode 100644 extern/libpng/include/contrib/pngminim/decoder/makefile create mode 100644 extern/libpng/include/contrib/pngminim/decoder/pngusr.dfa create mode 100644 extern/libpng/include/contrib/pngminim/decoder/pngusr.h create mode 100644 extern/libpng/include/contrib/pngminim/encoder/README create mode 100644 extern/libpng/include/contrib/pngminim/encoder/makefile create mode 100644 extern/libpng/include/contrib/pngminim/encoder/pngusr.dfa create mode 100644 extern/libpng/include/contrib/pngminim/encoder/pngusr.h create mode 100644 extern/libpng/include/contrib/pngminim/preader/README create mode 100644 extern/libpng/include/contrib/pngminim/preader/makefile create mode 100644 extern/libpng/include/contrib/pngminim/preader/pngusr.dfa create mode 100644 extern/libpng/include/contrib/pngminim/preader/pngusr.h create mode 100644 extern/libpng/include/contrib/pngminus/README create mode 100644 extern/libpng/include/contrib/pngminus/makefile.std create mode 100644 extern/libpng/include/contrib/pngminus/makefile.tc3 create mode 100644 extern/libpng/include/contrib/pngminus/makevms.com create mode 100644 extern/libpng/include/contrib/pngminus/png2pnm.bat create mode 100644 extern/libpng/include/contrib/pngminus/png2pnm.c create mode 100644 extern/libpng/include/contrib/pngminus/png2pnm.sh create mode 100644 extern/libpng/include/contrib/pngminus/pngminus.bat create mode 100644 extern/libpng/include/contrib/pngminus/pngminus.sh create mode 100644 extern/libpng/include/contrib/pngminus/pnm2png.bat create mode 100644 extern/libpng/include/contrib/pngminus/pnm2png.c create mode 100644 extern/libpng/include/contrib/pngminus/pnm2png.sh create mode 100644 extern/libpng/include/contrib/pngsuite/README create mode 100644 extern/libpng/include/contrib/pngsuite/basn0g01.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn0g02.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn0g04.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn0g08.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn0g16.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn2c08.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn2c16.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn3p01.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn3p02.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn3p04.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn4a08.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn4a16.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn6a08.png create mode 100644 extern/libpng/include/contrib/pngsuite/basn6a16.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbbn1g04.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbbn2c16.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbbn3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbgn2c16.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbgn3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbrn2c08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbwn1g16.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbwn3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftbyn3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftp0n1g08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftp0n2c08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftp0n3p08.png create mode 100644 extern/libpng/include/contrib/pngsuite/ftp1n3p08.png create mode 100644 extern/libpng/include/contrib/visupng/PngFile.c create mode 100644 extern/libpng/include/contrib/visupng/PngFile.h create mode 100644 extern/libpng/include/contrib/visupng/README.txt create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.c create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.dsp create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.dsw create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.ico create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.png create mode 100644 extern/libpng/include/contrib/visupng/VisualPng.rc create mode 100644 extern/libpng/include/contrib/visupng/cexcept.h create mode 100644 extern/libpng/include/contrib/visupng/resource.h create mode 100755 extern/libpng/include/depcomp create mode 100644 extern/libpng/include/example.c create mode 100644 extern/libpng/include/libpng-manual.txt create mode 100644 extern/libpng/include/libpng.3 create mode 100644 extern/libpng/include/libpng.pc.in create mode 100644 extern/libpng/include/libpngpf.3 create mode 100755 extern/libpng/include/ltmain.sh create mode 100755 extern/libpng/include/missing create mode 100644 extern/libpng/include/png.5 create mode 100644 extern/libpng/include/pngbar.jpg create mode 100644 extern/libpng/include/pngbar.png create mode 100644 extern/libpng/include/pnglibconf.h create mode 100644 extern/libpng/include/projects/visualc71/PRJ0041.mak create mode 100644 extern/libpng/include/projects/visualc71/README.txt create mode 100644 extern/libpng/include/projects/visualc71/README_zlib.txt create mode 100644 extern/libpng/include/projects/visualc71/libpng.sln create mode 100644 extern/libpng/include/projects/visualc71/libpng.vcproj create mode 100644 extern/libpng/include/projects/visualc71/pngtest.vcproj create mode 100644 extern/libpng/include/projects/visualc71/zlib.vcproj create mode 100644 extern/libpng/include/projects/vstudio/libpng/libpng.vcxproj create mode 100644 extern/libpng/include/projects/vstudio/pnglibconf/pnglibconf.vcxproj create mode 100644 extern/libpng/include/projects/vstudio/pngtest/pngtest.vcxproj create mode 100644 extern/libpng/include/projects/vstudio/pngvalid/pngvalid.vcxproj create mode 100644 extern/libpng/include/projects/vstudio/readme.txt create mode 100644 extern/libpng/include/projects/vstudio/vstudio.sln create mode 100644 extern/libpng/include/projects/vstudio/zlib.props create mode 100644 extern/libpng/include/projects/vstudio/zlib/zlib.vcxproj create mode 100644 extern/libpng/include/scripts/README.txt create mode 100644 extern/libpng/include/scripts/SCOPTIONS.ppc create mode 100755 extern/libpng/include/scripts/checksym.awk create mode 100755 extern/libpng/include/scripts/chkfmt create mode 100644 extern/libpng/include/scripts/def.dfn create mode 100644 extern/libpng/include/scripts/descrip.mms create mode 100755 extern/libpng/include/scripts/libpng-config-body.in create mode 100755 extern/libpng/include/scripts/libpng-config-head.in create mode 100644 extern/libpng/include/scripts/libpng.pc.in create mode 100644 extern/libpng/include/scripts/list create mode 100644 extern/libpng/include/scripts/makefile.32sunu create mode 100644 extern/libpng/include/scripts/makefile.64sunu create mode 100644 extern/libpng/include/scripts/makefile.acorn create mode 100644 extern/libpng/include/scripts/makefile.aix create mode 100644 extern/libpng/include/scripts/makefile.amiga create mode 100644 extern/libpng/include/scripts/makefile.atari create mode 100644 extern/libpng/include/scripts/makefile.bc32 create mode 100644 extern/libpng/include/scripts/makefile.beos create mode 100644 extern/libpng/include/scripts/makefile.bor create mode 100644 extern/libpng/include/scripts/makefile.cegcc create mode 100644 extern/libpng/include/scripts/makefile.darwin create mode 100644 extern/libpng/include/scripts/makefile.dec create mode 100644 extern/libpng/include/scripts/makefile.dj2 create mode 100644 extern/libpng/include/scripts/makefile.elf create mode 100644 extern/libpng/include/scripts/makefile.freebsd create mode 100644 extern/libpng/include/scripts/makefile.gcc create mode 100644 extern/libpng/include/scripts/makefile.hp64 create mode 100644 extern/libpng/include/scripts/makefile.hpgcc create mode 100644 extern/libpng/include/scripts/makefile.hpux create mode 100644 extern/libpng/include/scripts/makefile.ibmc create mode 100644 extern/libpng/include/scripts/makefile.intel create mode 100644 extern/libpng/include/scripts/makefile.knr create mode 100644 extern/libpng/include/scripts/makefile.linux create mode 100644 extern/libpng/include/scripts/makefile.mips create mode 100644 extern/libpng/include/scripts/makefile.msc create mode 100644 extern/libpng/include/scripts/makefile.ne12bsd create mode 100644 extern/libpng/include/scripts/makefile.netbsd create mode 100644 extern/libpng/include/scripts/makefile.openbsd create mode 100644 extern/libpng/include/scripts/makefile.sco create mode 100644 extern/libpng/include/scripts/makefile.sggcc create mode 100644 extern/libpng/include/scripts/makefile.sgi create mode 100644 extern/libpng/include/scripts/makefile.so9 create mode 100644 extern/libpng/include/scripts/makefile.solaris create mode 100644 extern/libpng/include/scripts/makefile.solaris-x86 create mode 100644 extern/libpng/include/scripts/makefile.std create mode 100644 extern/libpng/include/scripts/makefile.sunos create mode 100644 extern/libpng/include/scripts/makefile.tc3 create mode 100644 extern/libpng/include/scripts/makefile.vcwin32 create mode 100644 extern/libpng/include/scripts/makefile.watcom create mode 100644 extern/libpng/include/scripts/makevms.com create mode 100755 extern/libpng/include/scripts/options.awk create mode 100644 extern/libpng/include/scripts/pnglibconf.dfa create mode 100644 extern/libpng/include/scripts/pnglibconf.h create mode 100755 extern/libpng/include/scripts/pnglibconf.mak create mode 100644 extern/libpng/include/scripts/pngwin.rc create mode 100644 extern/libpng/include/scripts/smakefile.ppc create mode 100644 extern/libpng/include/scripts/sym.dfn create mode 100644 extern/libpng/include/scripts/symbols.def create mode 100644 extern/libpng/include/scripts/symbols.dfn create mode 100644 extern/libpng/include/scripts/vers.dfn diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index b0540e5505..a70652bcd4 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -31,6 +31,28 @@ 2BA7925F1304F20D002BD8E1 /* NotesLoaderSSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */; }; 2BA792601304F20D002BD8E1 /* NotesWriterSSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */; }; 2BA792611304F20D002BD8E1 /* NotesWriterSSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA7925D1304F20D002BD8E1 /* NotesWriterSSC.h */; }; + 2BC6132413773C8E00CC8BBD /* png.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6130D13773C8E00CC8BBD /* png.c */; }; + 2BC6132513773C8E00CC8BBD /* png.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6130E13773C8E00CC8BBD /* png.h */; }; + 2BC6132613773C8E00CC8BBD /* pngconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6130F13773C8E00CC8BBD /* pngconf.h */; }; + 2BC6132713773C8E00CC8BBD /* pngdebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6131013773C8E00CC8BBD /* pngdebug.h */; }; + 2BC6132813773C8E00CC8BBD /* pngerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131113773C8E00CC8BBD /* pngerror.c */; }; + 2BC6132913773C8E00CC8BBD /* pngget.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131213773C8E00CC8BBD /* pngget.c */; }; + 2BC6132A13773C8E00CC8BBD /* pnginfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6131313773C8E00CC8BBD /* pnginfo.h */; }; + 2BC6132B13773C8E00CC8BBD /* pngmem.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131413773C8E00CC8BBD /* pngmem.c */; }; + 2BC6132C13773C8E00CC8BBD /* pngpread.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131513773C8E00CC8BBD /* pngpread.c */; }; + 2BC6132D13773C8E00CC8BBD /* pngpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6131613773C8E00CC8BBD /* pngpriv.h */; }; + 2BC6132E13773C8E00CC8BBD /* pngread.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131713773C8E00CC8BBD /* pngread.c */; }; + 2BC6132F13773C8E00CC8BBD /* pngrio.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131813773C8E00CC8BBD /* pngrio.c */; }; + 2BC6133013773C8E00CC8BBD /* pngrtran.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131913773C8E00CC8BBD /* pngrtran.c */; }; + 2BC6133113773C8E00CC8BBD /* pngrutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131A13773C8E00CC8BBD /* pngrutil.c */; }; + 2BC6133213773C8E00CC8BBD /* pngset.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131B13773C8E00CC8BBD /* pngset.c */; }; + 2BC6133313773C8E00CC8BBD /* pngstruct.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6131C13773C8E00CC8BBD /* pngstruct.h */; }; + 2BC6133513773C8E00CC8BBD /* pngtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6131E13773C8E00CC8BBD /* pngtrans.c */; }; + 2BC6133713773C8E00CC8BBD /* pngwio.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6132013773C8E00CC8BBD /* pngwio.c */; }; + 2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6132113773C8E00CC8BBD /* pngwrite.c */; }; + 2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6132213773C8E00CC8BBD /* pngwtran.c */; }; + 2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BC6132313773C8E00CC8BBD /* pngwutil.c */; }; + 2BC6133E13773D2C00CC8BBD /* pnglibconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BC6133D13773D2C00CC8BBD /* pnglibconf.h */; }; 2BD06FEE137242680018CB9F /* json_batchallocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BD06FDD137240CF0018CB9F /* json_batchallocator.h */; }; 2BD06FEF137242680018CB9F /* json_internalarray.inl in Resources */ = {isa = PBXBuildFile; fileRef = 2BD06FDE137240CF0018CB9F /* json_internalarray.inl */; }; 2BD06FF0137242680018CB9F /* json_internalmap.inl in Resources */ = {isa = PBXBuildFile; fileRef = 2BD06FDF137240CF0018CB9F /* json_internalmap.inl */; }; @@ -157,12 +179,10 @@ AA21D59D0712ADE4008B825F /* ScreenDimensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA21D59C0712ADE4008B825F /* ScreenDimensions.cpp */; }; AA21E4790A9826CD00684CEA /* libjpeg_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4730A9826CD00684CEA /* libjpeg_link.a */; }; AA21E47B0A9826CD00684CEA /* libogg_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4750A9826CD00684CEA /* libogg_link.a */; }; - AA21E47C0A9826CD00684CEA /* libpng_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4760A9826CD00684CEA /* libpng_link.a */; }; AA21E47D0A9826CD00684CEA /* libtheora_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4770A9826CD00684CEA /* libtheora_link.a */; }; AA21E47E0A9826CD00684CEA /* libvorbis_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4780A9826CD00684CEA /* libvorbis_link.a */; }; AA21E47F0A9826CD00684CEA /* libjpeg_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4730A9826CD00684CEA /* libjpeg_link.a */; }; AA21E4810A9826CD00684CEA /* libogg_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4750A9826CD00684CEA /* libogg_link.a */; }; - AA21E4820A9826CD00684CEA /* libpng_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4760A9826CD00684CEA /* libpng_link.a */; }; AA21E4830A9826CD00684CEA /* libtheora_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4770A9826CD00684CEA /* libtheora_link.a */; }; AA21E4840A9826CD00684CEA /* libvorbis_link.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA21E4780A9826CD00684CEA /* libvorbis_link.a */; }; AA22CBA506DE909C0083BA97 /* ScreenNetSelectMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA22CBA306DE909C0083BA97 /* ScreenNetSelectMusic.cpp */; }; @@ -1782,6 +1802,28 @@ 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSSC.h; path = ../src/NotesLoaderSSC.h; sourceTree = SOURCE_ROOT; }; 2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesWriterSSC.cpp; path = ../src/NotesWriterSSC.cpp; sourceTree = SOURCE_ROOT; }; 2BA7925D1304F20D002BD8E1 /* NotesWriterSSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesWriterSSC.h; path = ../src/NotesWriterSSC.h; sourceTree = SOURCE_ROOT; }; + 2BC6130D13773C8E00CC8BBD /* png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = png.c; path = ../extern/libpng/include/png.c; sourceTree = SOURCE_ROOT; }; + 2BC6130E13773C8E00CC8BBD /* png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = png.h; path = ../extern/libpng/include/png.h; sourceTree = SOURCE_ROOT; }; + 2BC6130F13773C8E00CC8BBD /* pngconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngconf.h; path = ../extern/libpng/include/pngconf.h; sourceTree = SOURCE_ROOT; }; + 2BC6131013773C8E00CC8BBD /* pngdebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngdebug.h; path = ../extern/libpng/include/pngdebug.h; sourceTree = SOURCE_ROOT; }; + 2BC6131113773C8E00CC8BBD /* pngerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngerror.c; path = ../extern/libpng/include/pngerror.c; sourceTree = SOURCE_ROOT; }; + 2BC6131213773C8E00CC8BBD /* pngget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngget.c; path = ../extern/libpng/include/pngget.c; sourceTree = SOURCE_ROOT; }; + 2BC6131313773C8E00CC8BBD /* pnginfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pnginfo.h; path = ../extern/libpng/include/pnginfo.h; sourceTree = SOURCE_ROOT; }; + 2BC6131413773C8E00CC8BBD /* pngmem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngmem.c; path = ../extern/libpng/include/pngmem.c; sourceTree = SOURCE_ROOT; }; + 2BC6131513773C8E00CC8BBD /* pngpread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngpread.c; path = ../extern/libpng/include/pngpread.c; sourceTree = SOURCE_ROOT; }; + 2BC6131613773C8E00CC8BBD /* pngpriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngpriv.h; path = ../extern/libpng/include/pngpriv.h; sourceTree = SOURCE_ROOT; }; + 2BC6131713773C8E00CC8BBD /* pngread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngread.c; path = ../extern/libpng/include/pngread.c; sourceTree = SOURCE_ROOT; }; + 2BC6131813773C8E00CC8BBD /* pngrio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrio.c; path = ../extern/libpng/include/pngrio.c; sourceTree = SOURCE_ROOT; }; + 2BC6131913773C8E00CC8BBD /* pngrtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrtran.c; path = ../extern/libpng/include/pngrtran.c; sourceTree = SOURCE_ROOT; }; + 2BC6131A13773C8E00CC8BBD /* pngrutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngrutil.c; path = ../extern/libpng/include/pngrutil.c; sourceTree = SOURCE_ROOT; }; + 2BC6131B13773C8E00CC8BBD /* pngset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngset.c; path = ../extern/libpng/include/pngset.c; sourceTree = SOURCE_ROOT; }; + 2BC6131C13773C8E00CC8BBD /* pngstruct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pngstruct.h; path = ../extern/libpng/include/pngstruct.h; sourceTree = SOURCE_ROOT; }; + 2BC6131E13773C8E00CC8BBD /* pngtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngtrans.c; path = ../extern/libpng/include/pngtrans.c; sourceTree = SOURCE_ROOT; }; + 2BC6132013773C8E00CC8BBD /* pngwio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwio.c; path = ../extern/libpng/include/pngwio.c; sourceTree = SOURCE_ROOT; }; + 2BC6132113773C8E00CC8BBD /* pngwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwrite.c; path = ../extern/libpng/include/pngwrite.c; sourceTree = SOURCE_ROOT; }; + 2BC6132213773C8E00CC8BBD /* pngwtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwtran.c; path = ../extern/libpng/include/pngwtran.c; sourceTree = SOURCE_ROOT; }; + 2BC6132313773C8E00CC8BBD /* pngwutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pngwutil.c; path = ../extern/libpng/include/pngwutil.c; sourceTree = SOURCE_ROOT; }; + 2BC6133D13773D2C00CC8BBD /* pnglibconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pnglibconf.h; path = ../extern/libpng/include/pnglibconf.h; sourceTree = SOURCE_ROOT; }; 2BD06FDD137240CF0018CB9F /* json_batchallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = json_batchallocator.h; path = ../extern/jsoncpp/src/lib_json/json_batchallocator.h; sourceTree = SOURCE_ROOT; }; 2BD06FDE137240CF0018CB9F /* json_internalarray.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_internalarray.inl; path = ../extern/jsoncpp/src/lib_json/json_internalarray.inl; sourceTree = SOURCE_ROOT; }; 2BD06FDF137240CF0018CB9F /* json_internalmap.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = json_internalmap.inl; path = ../extern/jsoncpp/src/lib_json/json_internalmap.inl; sourceTree = SOURCE_ROOT; }; @@ -1924,7 +1966,6 @@ AA21D5A10712AE16008B825F /* ThemeMetric.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ThemeMetric.h; path = ../src/ThemeMetric.h; sourceTree = ""; }; AA21E4730A9826CD00684CEA /* libjpeg_link.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjpeg_link.a; sourceTree = ""; }; AA21E4750A9826CD00684CEA /* libogg_link.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libogg_link.a; sourceTree = ""; }; - AA21E4760A9826CD00684CEA /* libpng_link.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libpng_link.a; sourceTree = ""; }; AA21E4770A9826CD00684CEA /* libtheora_link.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libtheora_link.a; sourceTree = ""; }; AA21E4780A9826CD00684CEA /* libvorbis_link.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libvorbis_link.a; sourceTree = ""; }; AA22CBA306DE909C0083BA97 /* ScreenNetSelectMusic.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; name = ScreenNetSelectMusic.cpp; path = ../src/ScreenNetSelectMusic.cpp; sourceTree = ""; }; @@ -3012,7 +3053,6 @@ AA77E8B108B6ABD500FA24CA /* vecLib.framework in Frameworks */, AA21E4790A9826CD00684CEA /* libjpeg_link.a in Frameworks */, AA21E47B0A9826CD00684CEA /* libogg_link.a in Frameworks */, - AA21E47C0A9826CD00684CEA /* libpng_link.a in Frameworks */, AA21E47D0A9826CD00684CEA /* libtheora_link.a in Frameworks */, AA21E47E0A9826CD00684CEA /* libvorbis_link.a in Frameworks */, AAE782030AC7E64D00AEFC64 /* liblua-5.1.a in Frameworks */, @@ -3040,7 +3080,6 @@ AA40D51F09A08D650068C0D5 /* vecLib.framework in Frameworks */, AA21E47F0A9826CD00684CEA /* libjpeg_link.a in Frameworks */, AA21E4810A9826CD00684CEA /* libogg_link.a in Frameworks */, - AA21E4820A9826CD00684CEA /* libpng_link.a in Frameworks */, AA21E4830A9826CD00684CEA /* libtheora_link.a in Frameworks */, AA21E4840A9826CD00684CEA /* libvorbis_link.a in Frameworks */, AAE782040AC7E65200AEFC64 /* liblua-5.1.a in Frameworks */, @@ -3230,11 +3269,41 @@ name = NoteParsing; sourceTree = ""; }; + 2BC6130C13773C6800CC8BBD /* libpng */ = { + isa = PBXGroup; + children = ( + 2BC6130D13773C8E00CC8BBD /* png.c */, + 2BC6130E13773C8E00CC8BBD /* png.h */, + 2BC6130F13773C8E00CC8BBD /* pngconf.h */, + 2BC6131013773C8E00CC8BBD /* pngdebug.h */, + 2BC6131113773C8E00CC8BBD /* pngerror.c */, + 2BC6131213773C8E00CC8BBD /* pngget.c */, + 2BC6131313773C8E00CC8BBD /* pnginfo.h */, + 2BC6133D13773D2C00CC8BBD /* pnglibconf.h */, + 2BC6131413773C8E00CC8BBD /* pngmem.c */, + 2BC6131513773C8E00CC8BBD /* pngpread.c */, + 2BC6131613773C8E00CC8BBD /* pngpriv.h */, + 2BC6131713773C8E00CC8BBD /* pngread.c */, + 2BC6131813773C8E00CC8BBD /* pngrio.c */, + 2BC6131913773C8E00CC8BBD /* pngrtran.c */, + 2BC6131A13773C8E00CC8BBD /* pngrutil.c */, + 2BC6131B13773C8E00CC8BBD /* pngset.c */, + 2BC6131C13773C8E00CC8BBD /* pngstruct.h */, + 2BC6131E13773C8E00CC8BBD /* pngtrans.c */, + 2BC6132013773C8E00CC8BBD /* pngwio.c */, + 2BC6132113773C8E00CC8BBD /* pngwrite.c */, + 2BC6132213773C8E00CC8BBD /* pngwtran.c */, + 2BC6132313773C8E00CC8BBD /* pngwutil.c */, + ); + name = libpng; + sourceTree = ""; + }; 2BDB87261371F7FF00E6FD3A /* extern */ = { isa = PBXGroup; children = ( EE879B8E132E06C50078FDDC /* glew-1.5.8 */, EE906F6F12BF3A5B00146C96 /* json */, + 2BC6130C13773C6800CC8BBD /* libpng */, AA7C8A7F0B6744F600FD9940 /* libtommath */, AA7C8B920B67467C00FD9940 /* libtomcrypt */, AAE781870AC7E46E00AEFC64 /* lua-5.1 */, @@ -4757,7 +4826,6 @@ AAA0704D0CE5082D005A3060 /* libffmpeg_link.a */, AA21E4730A9826CD00684CEA /* libjpeg_link.a */, AA21E4750A9826CD00684CEA /* libogg_link.a */, - AA21E4760A9826CD00684CEA /* libpng_link.a */, AA21E4770A9826CD00684CEA /* libtheora_link.a */, AA21E4780A9826CD00684CEA /* libvorbis_link.a */, AA059E2A0B8F0C66006F8139 /* libz_link.a */, @@ -4967,6 +5035,13 @@ EE879B63132DEE720078FDDC /* RageDisplay_Legacy.h in Headers */, 2B76698B132FF71500586512 /* NotesLoaderSMA.h in Headers */, 2BD06FEE137242680018CB9F /* json_batchallocator.h in Headers */, + 2BC6132513773C8E00CC8BBD /* png.h in Headers */, + 2BC6132613773C8E00CC8BBD /* pngconf.h in Headers */, + 2BC6132713773C8E00CC8BBD /* pngdebug.h in Headers */, + 2BC6132A13773C8E00CC8BBD /* pnginfo.h in Headers */, + 2BC6132D13773C8E00CC8BBD /* pngpriv.h in Headers */, + 2BC6133313773C8E00CC8BBD /* pngstruct.h in Headers */, + 2BC6133E13773D2C00CC8BBD /* pnglibconf.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6211,6 +6286,21 @@ 2BD06FF1137242680018CB9F /* json_reader.cpp in Sources */, 2BD06FF2137242680018CB9F /* json_value.cpp in Sources */, 2BD06FF4137242680018CB9F /* json_writer.cpp in Sources */, + 2BC6132413773C8E00CC8BBD /* png.c in Sources */, + 2BC6132813773C8E00CC8BBD /* pngerror.c in Sources */, + 2BC6132913773C8E00CC8BBD /* pngget.c in Sources */, + 2BC6132B13773C8E00CC8BBD /* pngmem.c in Sources */, + 2BC6132C13773C8E00CC8BBD /* pngpread.c in Sources */, + 2BC6132E13773C8E00CC8BBD /* pngread.c in Sources */, + 2BC6132F13773C8E00CC8BBD /* pngrio.c in Sources */, + 2BC6133013773C8E00CC8BBD /* pngrtran.c in Sources */, + 2BC6133113773C8E00CC8BBD /* pngrutil.c in Sources */, + 2BC6133213773C8E00CC8BBD /* pngset.c in Sources */, + 2BC6133513773C8E00CC8BBD /* pngtrans.c in Sources */, + 2BC6133713773C8E00CC8BBD /* pngwio.c in Sources */, + 2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */, + 2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */, + 2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/extern/libpng/include/CHANGES b/extern/libpng/include/CHANGES new file mode 100644 index 0000000000..fb069121a4 --- /dev/null +++ b/extern/libpng/include/CHANGES @@ -0,0 +1,3297 @@ +#if 0 +libpng_changes(){ /* +CHANGES - changes for libpng + +Version 0.2 + added reader into png.h + fixed small problems in stub file + +Version 0.3 + added pull reader + split up pngwrite.c to several files + added pnglib.txt + added example.c + cleaned up writer, adding a few new transformations + fixed some bugs in writer + interfaced with zlib 0.5 + added K&R support + added check for 64 KB blocks for 16 bit machines + +Version 0.4 + cleaned up code and commented code + simplified time handling into png_time + created png_color_16 and png_color_8 to handle color needs + cleaned up color type defines + fixed various bugs + made various names more consistent + interfaced with zlib 0.71 + cleaned up zTXt reader and writer (using zlib's Reset functions) + split transformations into pngrtran.c and pngwtran.c + +Version 0.5 + interfaced with zlib 0.8 + fixed many reading and writing bugs + saved using 3 spaces instead of tabs + +Version 0.6 + added png_large_malloc() and png_large_free() + added png_size_t + cleaned up some compiler warnings + added png_start_read_image() + +Version 0.7 + cleaned up lots of bugs + finished dithering and other stuff + added test program + changed name from pnglib to libpng + +Version 0.71 [June, 1995] + changed pngtest.png for zlib 0.93 + fixed error in libpng.txt and example.c + +Version 0.8 + cleaned up some bugs + added png_set_filler() + split up pngstub.c into pngmem.c, pngio.c, and pngerror.c + added #define's to remove unwanted code + moved png_info_init() to png.c + added old_size into png_realloc() + added functions to manually set filtering and compression info + changed compression parameters based on image type + optimized filter selection code + added version info + changed external functions passing floats to doubles (k&r problems?) + put all the configurable stuff in pngconf.h + enabled png_set_shift to work with paletted images on read + added png_read_update_info() - updates info structure with transformations + +Version 0.81 [August, 1995] + incorporated Tim Wegner's medium model code (thanks, Tim) + +Version 0.82 [September, 1995] + [unspecified changes] + +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.) + added first run progressive reader (barely tested) + +Version 0.86 [January, 1996] + fixed bugs + improved documentation + +Version 0.87 [January, 1996] + fixed medium model bugs + fixed other bugs introduced in 0.85 and 0.86 + added some minor documentation + +Version 0.88 [January, 1996] + fixed progressive bugs + replaced tabs with spaces + cleaned up documentation + added callbacks for read/write and warning/error functions + +Version 0.89 [July, 1996] + Added new initialization API to make libpng work better with shared libs + we now have png_create_read_struct(), png_create_write_struct(), + png_create_info_struct(), png_destroy_read_struct(), and + png_destroy_write_struct() instead of the separate calls to + malloc and png_read_init(), png_info_init(), and png_write_init() + Changed warning/error callback functions to fix bug - this means you + should use the new initialization API if you were using the old + png_set_message_fn() calls, and that the old API no longer exists + so that people are aware that they need to change their code + Changed filter selection API to allow selection of multiple filters + since it didn't work in previous versions of libpng anyways + Optimized filter selection code + Fixed png_set_background() to allow using an arbitrary RGB color for + paletted images + Fixed gamma and background correction for paletted images, so + png_correct_palette is not needed unless you are correcting an + external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED + in pngconf.h) - if nobody uses this, it may disappear in the future. + Fixed bug with Borland 64K memory allocation (Alexander Lehmann) + Fixed bug in interlace handling (Smarasderagd, I think) + Added more error checking for writing and image to reduce invalid files + Separated read and write functions so that they won't both be linked + into a binary when only reading or writing functionality is used + New pngtest image also has interlacing and zTXt + Updated documentation to reflect new API + +Version 0.90 [January, 1997] + Made CRC errors/warnings on critical and ancillary chunks configurable + libpng will use the zlib CRC routines by (compile-time) default + Changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) + Added external C++ wrapper statements to png.h (Gilles Dauphin) + Allow PNG file to be read when some or all of file signature has already + been read from the beginning of the stream. ****This affects the size + of info_struct and invalidates all programs that use a shared libpng**** + Fixed png_filler() declarations + Fixed? background color conversions + Fixed order of error function pointers to match documentation + Current chunk name is now available in png_struct to reduce the number + of nearly identical error messages (will simplify multi-lingual + support when available) + Try to get ready for unknown-chunk callback functions: + - previously read critical chunks are flagged, so the chunk handling + routines can determine if the chunk is in the right place + - all chunk handling routines have the same prototypes, so we will + be able to handle all chunks via a callback mechanism + Try to fix Linux "setjmp" buffer size problems + Removed png_large_malloc, png_large_free, and png_realloc functions. + +Version 0.95 [March, 1997] + Fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never + Fixed bug in PNG file signature compares when start != 0 + Changed parameter type of png_set_filler(...filler...) from png_byte + to png_uint_32 + Added test for MACOS to ensure that both math.h and fp.h are not #included + Added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) + Added "packswap" transformation, which changes the endianness of + packed-pixel bytes (Kevin Bracey) + Added "strip_alpha" transformation, which removes the alpha channel of + input images without using it (not necessarily a good idea) + Added "swap_alpha" transformation, which puts the alpha channel in front + of the color bytes instead of after + Removed all implicit variable tests which assume NULL == 0 (I think) + Changed several variables to "png_size_t" to show 16/32-bit limitations + Added new pCAL chunk read/write support + Added experimental filter selection weighting (Greg Roelofs) + Removed old png_set_rgbx() and png_set_xrgb() functions that have been + obsolete for about 2 years now (use png_set_filler() instead) + Added macros to read 16- and 32-bit ints directly from buffer, to be + used only on those systems that support it (namely PowerPC and 680x0) + With some testing, this may become the default for MACOS/PPC systems. + Only calculate CRC on data if we are going to use it + Added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? + Added macros for simple libpng debugging output selectable at compile time + Removed PNG_READ_END_MODE in progressive reader (Smarasderagd) + More description of info_struct in libpng.txt and png.h + More instructions in example.c + More chunk types tested in pngtest.c + Renamed pngrcb.c to pngset.c, and all png_read_ functions to be + png_set_. We now have corresponding png_get_ + functions in pngget.c to get information in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). + +Version 0.96 [May, 1997] + Fixed serious bug with < 8bpp images introduced in 0.95 + Fixed 256-color transparency bug (Greg Roelofs) + Fixed up documentation (Greg Roelofs, Laszlo Nyul) + Fixed "error" in pngconf.h for Linux setjmp() behaviour + Fixed DOS medium model support (Tim Wegner) + Fixed png_check_keyword() for case with error in static string text + Added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + Added typecasts to quiet compiler errors + Added more debugging info + +Version 0.97 [January, 1998] + Removed PNG_USE_OWN_CRC capability + Relocated png_set_crc_action from pngrutil.c to pngrtran.c + Fixed typecasts of "new_key", etc. (Andreas Dilger) + Added RFC 1152 [sic] date support + Fixed bug in gamma handling of 4-bit grayscale + Added 2-bit grayscale gamma handling (Glenn R-P) + Added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + Minor corrections in libpng.txt + Added simple sRGB support (Glenn R-P) + Easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + Added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + Repaired PNG_NO_STDIO behaviour + Tested NODIV support and made it default behaviour (Greg Roelofs) + Added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + Regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) + +Version 0.98 [January, 1998] + Cleaned up some typos in libpng.txt and in code documentation + Fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + Cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + Changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + Changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + Added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + Changed srgb_intent from png_byte to int to avoid compiler bugs + +Version 0.99 [January 30, 1998] + Free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + Fixed a longstanding "packswap" bug in pngtrans.c + Fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + Fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + Changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + Added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + Added TARGET_MACOS similar to zlib-1.0.8 + Define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + Added type casting to all png_malloc() function calls + +Version 0.99a [January 31, 1998] + Added type casts and parentheses to all returns that return a value.(Tim W.) + +Version 0.99b [February 4, 1998] + Added type cast png_uint_32 on malloc function calls where needed. + Changed type of num_hist from png_uint_32 to int (same as num_palette). + Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. + Renamed makefile.elf to makefile.lnx. + +Version 0.99c [February 7, 1998] + More type casting. Removed erroneous overflow test in pngmem.c. + Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. + Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. + +Version 0.99d [February 11, 1998] + Renamed "far_to_near()" "png_far_to_near()" + Revised libpng.3 + Version 99c "buffered" operations didn't work as intended. Replaced them + with png_memcpy_check() and png_memset_check(). + Added many "if (png_ptr == NULL) return" to quell compiler warnings about + unused png_ptr, mostly in pngget.c and pngset.c. + Check for overlength tRNS chunk present when indexed-color PLTE is read. + Cleaned up spelling errors in libpng.3/libpng.txt + Corrected a problem with png_get_tRNS() which returned undefined trans array + +Version 0.99e [February 28, 1998] + Corrected png_get_tRNS() again. + Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". + Touched up example.c to make more of it compileable, although the entire + file still can't be compiled (Willem van Schaik) + Fixed a bug in png_do_shift() (Bryan Tsai) + Added a space in png.h prototype for png_write_chunk_start() + Replaced pngtest.png with one created with zlib 1.1.1 + Changed pngtest to report PASS even when file size is different (Jean-loup G.) + Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) + +Version 0.99f [March 5, 1998] + Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) + Moved makefiles into a "scripts" directory, and added INSTALL instruction file + Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) + Added pointers to "note on libpng versions" in makefile.lnx and README + Added row callback feature when reading and writing nonprogressive rows + and added a test of this feature in pngtest.c + Added user transform callbacks, with test of the feature in pngtest.c + +Version 0.99g [March 6, 1998, morning] + Minor changes to pngtest.c to suppress compiler warnings. + Removed "beta" language from documentation. + +Version 0.99h [March 6, 1998, evening] + Minor changes to previous minor changes to pngtest.c + Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + Added user transform capability + +Version 1.00 [March 7, 1998] + Changed several typedefs in pngrutil.c + Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) + Replaced "while(1)" with "for(;;)" + Added PNGARG() to prototypes in pngtest.c and removed some prototypes + Updated some of the makefiles (Tom Lane) + Changed some typedefs (s_start, etc.) in pngrutil.c + Fixed dimensions of "short_months" array in pngwrite.c + Replaced ansi2knr.c with the one from jpeg-v6 + +Version 1.0.0 [March 8, 1998] + Changed name from 1.00 to 1.0.0 (Adam Costello) + Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) + +Version 1.0.0a [March 9, 1998] + Fixed three bugs in pngrtran.c to make gamma+background handling consistent + (Greg Roelofs) + Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) + Make months range from 1-12 in png_convert_to_rfc1123 + +Version 1.0.0b [March 13, 1998] + Quieted compiler complaints about two empty "for" loops in pngrutil.c + Minor changes to makefile.s2x + Removed #ifdef/#endif around a png_free() in pngread.c + +Version 1.0.1 [March 14, 1998] + Changed makefile.s2x to reduce security risk of using a relative pathname + Fixed some typos in the documentation (Greg). + Fixed a problem with value of "channels" returned by png_read_update_info() + +Version 1.0.1a [April 21, 1998] + Optimized Paeth calculations by replacing abs() function calls with intrinsics + plus other loop optimizations. Improves avg decoding speed by about 20%. + Commented out i386istic "align" compiler flags in makefile.lnx. + Reduced the default warning level in some makefiles, to make them consistent. + Removed references to IJG and JPEG in the ansi2knr.c copyright statement. + Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. + Added grayscale and 16-bit capability to png_do_read_filler(). + Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes + too large when writing an image with bit_depth < 8 (Bob Dellaca). + Corrected some bugs in the experimental weighted filtering heuristics. + Moved a misplaced pngrutil code block that truncates tRNS if it has more + than num_palette entries -- test was done before num_palette was defined. + Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). + Changed compiler flags in makefile.wat for better optimization + (Pawel Mrochen). + +Version 1.0.1b [May 2, 1998] + Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). + Relocated the png_composite macros from pngrtran.c to png.h (Greg). + Added makefile.sco (contributed by Mike Hopkirk). + Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. + Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. + More work on the Paeth-filtering, achieving imperceptible speedup + (A Kleinert). + More work on loop optimization which may help when compiled with C++ + compilers. + Added warnings when people try to use transforms they've defined out. + Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. + Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) + +Version 1.0.1c [May 11, 1998] + Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for + filler bytes should have been 0xff instead of 0xf. + Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. + Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED + out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h + Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, + for consistency, in pngconf.h + Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier + to remove unwanted capabilities via the compile line + Made some corrections to grammar (which, it's) in documentation (Greg). + Corrected example.c, use of row_pointers in png_write_image(). + +Version 1.0.1d [May 24, 1998] + Corrected several statements that used side effects illegally in pngrutil.c + and pngtrans.c, that were introduced in version 1.0.1b + Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) + More corrections to example.c, use of row_pointers in png_write_image() + and png_read_rows(). + Added pngdll.mak and pngdef.pas to scripts directory, contributed by + Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 + Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) + Changed several loops from count-down to count-up, for consistency. + +Version 1.0.1e [June 6, 1998] + Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and + added warnings when people try to set png_read_fn and png_write_fn in + the same structure. + Added a test such that png_do_gamma will be done when num_trans==0 + for truecolor images that have defined a background. This corrects an + error that was introduced in libpng-0.90 that can cause gamma processing + to be skipped. + Added tests in png.h to include "trans" and "trans_values" in structures + when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. + Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() + Moved png_convert_to_rfc_1123() from pngwrite.c to png.c + Added capability for user-provided malloc_fn() and free_fn() functions, + and revised pngtest.c to demonstrate their use, replacing the + PNGTEST_DEBUG_MEM feature. + Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). + +Version 1.0.2 [June 14, 1998] + Fixed two bugs in makefile.bor . + +Version 1.0.2a [December 30, 1998] + Replaced and extended code that was removed from png_set_filler() in 1.0.1a. + Fixed a bug in png_do_filler() that made it fail to write filler bytes in + the left-most pixel of each row (Kevin Bracey). + Changed "static pngcharp tIME_string" to "static char tIME_string[30]" + in pngtest.c (Duncan Simpson). + Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk + even when no tIME chunk was present in the source file. + Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. + Fixed a problem in png_read_push_finish_row(), which would not skip some + passes that it should skip, for images that are less than 3 pixels high. + Interchanged the order of calls to png_do_swap() and png_do_shift() + in pngwtran.c (John Cromer). + Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . + Changed "bad adaptive filter type" from error to warning in pngrutil.c . + Fixed a documentation error about default filtering with 8-bit indexed-color. + Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO + (L. Peter Deutsch). + Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. + Added png_get_copyright() and png_get_header_version() functions. + Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c + Added information about debugging in libpng.txt and libpng.3 . + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and + makefile.sco. + Removed lines after Dynamic Dependencies" in makefile.aco . + Revised makefile.dec to make a shared library (Jeremie Petit). + Removed trailing blanks from all files. + +Version 1.0.2a [January 6, 1999] + Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h + Added "if" tests to silence complaints about unused png_ptr in png.h and png.c + Changed "check_if_png" function in example.c to return true (nonzero) if PNG. + Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() + which is obsolete. + +Version 1.0.3 [January 14, 1999] + Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) + Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. + +Version 1.0.3a [August 12, 1999] + Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning + if an attempt is made to read an interlaced image when it's not supported. + Added check if png_ptr->trans is defined before freeing it in pngread.c + Modified the Y2K statement to include versions back to version 0.71 + Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c + Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) + Replaced leading blanks with tab characters in makefile.hux + Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. + Changed (float)red and (float)green to (double)red, (double)green + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). + Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). + Updated documentation to refer to the PNG-1.2 specification. + Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c + in makefile.knr, INSTALL, and README (L. Peter Deutsch) + Fixed bugs in calculation of the length of rowbytes when adding alpha + channels to 16-bit images, in pngrtran.c (Chris Nokleberg) + Added function png_set_user_transform_info() to store user_transform_ptr, + user_depth, and user_channels into the png_struct, and a function + png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) + Added function png_set_empty_plte_permitted() to make libpng useable + in MNG applications. + Corrected the typedef for png_free_ptr in png.h (Jesse Jones). + Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be + consistent with PNG-1.2, and allow variance of 500 before complaining. + Added assembler code contributed by Intel in file pngvcrd.c and modified + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, + Gilles Vollant) + Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. + Added some aliases for png_set_expand() in pngrtran.c, namely + png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() + (Greg Roelofs, in "PNG: The Definitive Guide"). + Added makefile.beo for BEOS on X86, contributed by Sander Stok. + +Version 1.0.3b [August 26, 1999] + Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h + Changed leading blanks to tabs in all makefiles. + Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. + Made alternate versions of png_set_expand() in pngrtran.c, namely + png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha + (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. + Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h + Revised calculation of num_blocks in pngmem.c to avoid a potentially + negative shift distance, whose results are undefined in the C language. + Added a check in pngset.c to prevent writing multiple tIME chunks. + Added a check in pngwrite.c to detect invalid small window_bits sizes. + +Version 1.0.3d [September 4, 1999] + Fixed type casting of igamma in pngrutil.c + Added new png_expand functions to scripts/pngdef.pas and pngos2.def + Added a demo read_user_transform_fn that examines the row filters in pngtest.c + +Version 1.0.4 [September 24, 1999] + Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined + Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h + Made several minor corrections to pngtest.c + Renamed the makefiles with longer but more user friendly extensions. + Copied the PNG copyright and license to a separate LICENSE file. + Revised documentation, png.h, and example.c to remove reference to + "viewing_gamma" which no longer appears in the PNG specification. + Revised pngvcrd.c to use MMX code for interlacing only on the final pass. + Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a + Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX + assembler code) and makefile.vcwin32 (doesn't). + Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) + Added a copy of pngnow.png to the distribution. + +Version 1.0.4a [September 25, 1999] + Increase max_pixel_depth in pngrutil.c if a user transform needs it. + Changed several division operations to right-shifts in pngvcrd.c + +Version 1.0.4b [September 30, 1999] + Added parentheses in line 3732 of pngvcrd.c + Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 + +Version 1.0.4c [October 1, 1999] + Added a "png_check_version" function in png.c and pngtest.c that will generate + a helpful compiler error if an old png.h is found in the search path. + Changed type of png_user_transform_depth|channels from int to png_byte. + +Version 1.0.4d [October 6, 1999] + Changed 0.45 to 0.45455 in png_set_sRGB() + Removed unused PLTE entries from pngnow.png + Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. + +Version 1.0.4e [October 10, 1999] + Fixed sign error in pngvcrd.c (Greg Roelofs) + Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) + +Version 1.0.4f [October 15, 1999] + Surrounded example.c code with #if 0 .. #endif to prevent people from + inadvertently trying to compile it. + Changed png_get_header_version() from a function to a macro in png.h + Added type casting mostly in pngrtran.c and pngwtran.c + Removed some pointless "ptr = NULL" in pngmem.c + Added a "contrib" directory containing the source code from Greg's book. + +Version 1.0.5 [October 15, 1999] + Minor editing of the INSTALL and README files. + +Version 1.0.5a [October 23, 1999] + Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) + Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) + Further optimization and bugfix of pngvcrd.c + Revised pngset.c so that it does not allocate or free memory in the user's + text_ptr structure. Instead, it makes its own copy. + Created separate write_end_info_struct in pngtest.c for a more severe test. + Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. + +Version 1.0.5b [November 23, 1999] + Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and + PNG_FLAG_WROTE_tIME from flags to mode. + Added png_write_info_before_PLTE() function. + Fixed some typecasting in contrib/gregbook/*.c + Updated scripts/makevms.com and added makevms.com to contrib/gregbook + and contrib/pngminus (Martin Zinser) + +Version 1.0.5c [November 26, 1999] + Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. + Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to + accommodate making DLL's: Moved usr_png_ver from global variable to function + png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and + eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays + into pngtypes.h. Eliminated use of global png_pass arrays. Declared the + png_CHNK and png_pass arrays to be "const". Made the global arrays + available to applications (although none are used in libpng itself) when + PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. + Removed some extraneous "-I" from contrib/pngminus/makefile.std + Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. + Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 + +Version 1.0.5d [November 29, 1999] + Add type cast (png_const_charp) two places in png.c + Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. + Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available + to applications a macro "PNG_USE_LOCAL_ARRAYS". + comment out (with #ifdef) all the new declarations when + PNG_USE_GLOBAL_ARRAYS is defined. + Added PNG_EXPORT_VAR macro to accommodate making DLL's. + +Version 1.0.5e [November 30, 1999] + Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text + structure; refactored the inflate/deflate support to make adding new chunks + with trailing compressed parts easier in the future, and added new functions + png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, + png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). + NOTE: Applications that write text chunks MUST define png_text->lang + before calling png_set_text(). It must be set to NULL if you want to + write tEXt or zTXt chunks. If you want your application to be able to + run with older versions of libpng, use + + #ifdef PNG_iTXt_SUPPORTED + png_text[i].lang = NULL; + #endif + + Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned + offsets (Eric S. Raymond). + Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into + PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED + macros, leaving the separate macros also available. + Removed comments on #endifs at the end of many short, non-nested #if-blocks. + +Version 1.0.5f [December 6, 1999] + Changed makefile.solaris to issue a warning about potential problems when + the ucb "ld" is in the path ahead of the ccs "ld". + Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. + Added sCAL chunk support (Eric S. Raymond). + +Version 1.0.5g [December 7, 1999] + Fixed "png_free_spallettes" typo in png.h + Added code to handle new chunks in pngpread.c + Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block + Added "translated_key" to png_text structure and png_write_iTXt(). + Added code in pngwrite.c to work around a newly discovered zlib bug. + +Version 1.0.5h [December 10, 1999] + NOTE: regarding the note for version 1.0.5e, the following must also + be included in your code: + png_text[i].translated_key = NULL; + Unknown chunk handling is now supported. + Option to eliminate all floating point support was added. Some new + fixed-point functions such as png_set_gAMA_fixed() were added. + Expanded tabs and removed trailing blanks in source files. + +Version 1.0.5i [December 13, 1999] + Added some type casts to silence compiler warnings. + Renamed "png_free_spalette" to "png_free_spalettes" for consistency. + Removed leading blanks from a #define in pngvcrd.c + Added some parameters to the new png_set_keep_unknown_chunks() function. + Added a test for up->location != 0 in the first instance of writing + unknown chunks in pngwrite.c + Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to + prevent recursion. + Added png_free_hIST() function. + Various patches to fix bugs in the sCAL and integer cHRM processing, + and to add some convenience macros for use with sCAL. + +Version 1.0.5j [December 21, 1999] + Changed "unit" parameter of png_write_sCAL from png_byte to int, to work + around buggy compilers. + Added new type "png_fixed_point" for integers that hold float*100000 values + Restored backward compatibility of tEXt/zTXt chunk processing: + Restored the first four members of png_text to the same order as v.1.0.5d. + Added members "lang_key" and "itxt_length" to png_text struct. Set + text_length=0 when "text" contains iTXt data. Use the "compression" + member to distinguish among tEXt/zTXt/iTXt types. Added + PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. + The "Note" above, about backward incompatibility of libpng-1.0.5e, no + longer applies. + Fixed png_read|write_iTXt() to read|write parameters in the right order, + and to write the iTXt chunk after IDAT if it appears in the end_ptr. + Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) + Reversed the order of trying to write floating-point and fixed-point gAMA. + +Version 1.0.5k [December 27, 1999] + Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" + Added png_handle_as_unknown() function (Glenn) + Added png_free_chunk_list() function and chunk_list and num_chunk_list members + of png_ptr. + Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. + Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings + about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) + Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). + Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. + Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). + +Version 1.0.5l [January 1, 2000] + Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() + for setting a callback function to handle unknown chunks and for + retrieving the associated user pointer (Glenn). + +Version 1.0.5m [January 7, 2000] + Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). + +Version 1.0.5n [January 9, 2000] + Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its + own memory for info_ptr->palette. This makes it safe for the calling + application to free its copy of the palette any time after it calls + png_set_PLTE(). + +Version 1.0.5o [January 20, 2000] + Cosmetic changes only (removed some trailing blanks and TABs) + +Version 1.0.5p [January 31, 2000] + Renamed pngdll.mak to makefile.bd32 + Cosmetic changes in pngtest.c + +Version 1.0.5q [February 5, 2000] + Relocated the makefile.solaris warning about PATH problems. + Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) + Revised makefile.gcmmx + Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros + +Version 1.0.5r [February 7, 2000] + Removed superfluous prototype for png_get_itxt from png.h + Fixed a bug in pngrtran.c that improperly expanded the background color. + Return *num_text=0 from png_get_text() when appropriate, and fix documentation + of png_get_text() in libpng.txt/libpng.3. + +Version 1.0.5s [February 18, 2000] + Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the + new error handler that's planned for the next libpng release, and changed + example.c, pngtest.c, and contrib programs to use this macro. + Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) + Fixed a bug in png_read_png() that caused it to fail to expand some images + that it should have expanded. + Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions + in pngget.c + Changed the allocation of palette, history, and trans arrays back to + the version 1.0.5 method (linking instead of copying) which restores + backward compatibility with version 1.0.5. Added some remarks about + that in example.c. Added "free_me" member to info_ptr and png_ptr + and added png_free_data() function. + Updated makefile.linux and makefile.gccmmx to make directories conditionally. + Made cosmetic changes to pngasmrd.h + Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). + Modified png_read_png() to allocate info_ptr->row_pointers only if it + hasn't already been allocated. + +Version 1.0.5t [March 4, 2000] + Changed png_jmp_env() migration aiding macro to png_jmpbuf(). + Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c + Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when + PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b + Files in contrib/gregbook were revised to use png_jmpbuf() and to select + a 24-bit visual if one is available, and to allow abbreviated options. + Files in contrib/pngminus were revised to use the png_jmpbuf() macro. + Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s + +Version 1.0.5u [March 5, 2000] + Simplified the code that detects old png.h in png.c and pngtest.c + Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) + Increased precision of rgb_to_gray calculations from 8 to 15 bits and + added png_set_rgb_to_gray_fixed() function. + Added makefile.bc32 (32-bit Borland C++, C mode) + +Version 1.0.5v [March 11, 2000] + Added some parentheses to the png_jmpbuf macro definition. + Updated references to the zlib home page, which has moved to freesoftware.com. + Corrected bugs in documentation regarding png_read_row() and png_write_row(). + Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. + Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, + revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) + +Version 1.0.6 [March 20, 2000] + Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c + Added makefile.sggcc (SGI IRIX with gcc) + +Version 1.0.6d [April 7, 2000] + Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO + Added data_length parameter to png_decompress_chunk() function + Revised documentation to remove reference to abandoned png_free_chnk functions + Fixed an error in png_rgb_to_gray_fixed() + Revised example.c, usage of png_destroy_write_struct(). + Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file + Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c + Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). + +Version 1.0.6e [April 9, 2000] + Added png_data_freer() function. + In the code that checks for over-length tRNS chunks, added check of + info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) + Minor revisions of libpng.txt/libpng.3. + Check for existing data and free it if the free_me flag is set, in png_set_*() + and png_handle_*(). + Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED + is defined. + Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c + and mentioned the purposes of the two macros in libpng.txt/libpng.3. + +Version 1.0.6f [April 14, 2000] + Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. + Add checks in png_set_text() for NULL members of the input text structure. + Revised libpng.txt/libpng.3. + Removed superfluous prototype for png_set_iTXt from png.h + Removed "else" from pngread.c, after png_error(), and changed "0" to "length". + Changed several png_errors about malformed ancillary chunks to png_warnings. + +Version 1.0.6g [April 24, 2000] + Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. + Relocated paragraph about png_set_background() in libpng.3/libpng.txt + and other revisions (Matthias Benckmann) + Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and + png_ptr members to restore binary compatibility with libpng-1.0.5 + (breaks compatibility with libpng-1.0.6). + +Version 1.0.6h [April 24, 2000] + Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds + libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) + This is a temporary change for test purposes. + +Version 1.0.6i [May 2, 2000] + Rearranged some members at the end of png_info and png_struct, to put + unknown_chunks_num and free_me within the original size of the png_structs + and free_me, png_read_user_fn, and png_free_fn within the original png_info, + because some old applications allocate the structs directly instead of + using png_create_*(). + Added documentation of user memory functions in libpng.txt/libpng.3 + Modified png_read_png so that it will use user_allocated row_pointers + if present, unless free_me directs that it be freed, and added description + of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. + Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version + 1.00) members of png_struct and png_info, to regain binary compatibility + when you define this macro. Capabilities lost in this event + are user transforms (new in version 1.0.0),the user transform pointer + (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, + the high-level interface, and unknown chunks support (all new in 1.0.6). + This was necessary because of old applications that allocate the structs + directly as authors were instructed to do in libpng-0.88 and earlier, + instead of using png_create_*(). + Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which + can be used to detect codes that directly allocate the structs, and + code to check these modes in png_read_init() and png_write_init() and + generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED + was not defined. + Added makefile.intel and updated makefile.watcom (Pawel Mrochen) + +Version 1.0.6j [May 3, 2000] + Overloaded png_read_init() and png_write_init() with macros that convert + calls to png_read_init_2() or png_write_init_2() that check the version + and structure sizes. + +Version 1.0.7beta11 [May 7, 2000] + Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes + which are no longer used. + Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + is defined. + Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory + overrun when old applications fill the info_ptr->text structure directly. + Added PNGAPI macro, and added it to the definitions of all exported functions. + Relocated version macro definitions ahead of the includes of zlib.h and + pngconf.h in png.h. + +Version 1.0.7beta12 [May 12, 2000] + Revised pngset.c to avoid a problem with expanding the png_debug macro. + Deleted some extraneous defines from pngconf.h + Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. + Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. + Added png_access_version_number() function. + Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). + Expanded libpng.3/libpng.txt information about png_data_freer(). + +Version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as + warnings instead of errors, as pngrutil.c does. + Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() + will actually write IDATs. + Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. + Make png_free_data() ignore its final parameter except when freeing data + that can have multiple instances (text, sPLT, unknowns). + Fixed a new bug in png_set_rows(). + Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. + Added png_set_invalid() function. + Fixed incorrect illustrations of png_destroy_write_struct() in example.c. + +Version 1.0.7beta15 [May 30, 2000] + Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce + fewer error messages. + Rearranged checks for Z_OK to check the most likely path first in pngpread.c + and pngwutil.c. + Added checks in pngtest.c for png_create_*() returning NULL, and mentioned + in libpng.txt/libpng.3 the need for applications to check this. + Changed names of png_default_*() functions in pngtest to pngtest_*(). + Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. + Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c + Set each pointer to NULL after freeing it in png_free_data(). + Worked around a problem in pngconf.h; AIX's strings.h defines an "index" + macro that conflicts with libpng's png_color_16.index. (Dimitri + Papadapoulos) + Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). + +Version 1.0.7beta16 [June 4, 2000] + Revised the workaround of AIX string.h "index" bug. + Added a check for overlength PLTE chunk in pngrutil.c. + Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer + indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. + Added a warning in png_decompress_chunk() when it runs out of data, e.g. + when it tries to read an erroneous PhotoShop iCCP chunk. + Added PNG_USE_DLL macro. + Revised the copyright/disclaimer/license notice. + Added contrib/msvctest directory + +Version 1.0.7rc1 [June 9, 2000] + Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) + Added contrib/visupng directory (Willem van Schaik) + +Version 1.0.7beta18 [June 23, 2000] + Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ + and do not redefine PNGAPI if it is passed in via a compiler directive. + Revised visupng/PngFile.c to remove returns from within the Try block. + Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. + Updated contrib/visupng/cexcept.h to version 1.0.0. + Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. + +Version 1.0.7rc2 [June 28, 2000] + Updated license to include disclaimers required by UCITA. + Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. + +Version 1.0.7 [July 1, 2000] + Revised the definition of "trans_values" in libpng.3/libpng.txt + +Version 1.0.8beta1 [July 8, 2000] + Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. + Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and + pngwutil.c. + Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. + Removed unused "#include " from png.c + Added WindowsCE support. + Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. + +Version 1.0.8beta2 [July 10, 2000] + Added project files to the wince directory and made further revisions + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. + +Version 1.0.8beta3 [July 11, 2000] + Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. + Further revisions to pngtest.c and files in the wince subdirectory. + +Version 1.0.8beta4 [July 14, 2000] + Added the files pngbar.png and pngbar.jpg to the distribution. + Added makefile.cygwin, and cygwin support in pngconf.h + Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) + +Version 1.0.8rc1 [July 16, 2000] + Revised png_debug() macros and statements to eliminate compiler warnings. + +Version 1.0.8 [July 24, 2000] + Added png_flush() in pngwrite.c, after png_write_IEND(). + Updated makefile.hpux to build a shared library. + +Version 1.0.9beta1 [November 10, 2000] + Fixed typo in scripts/makefile.hpux + Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) + Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Changed "cdrom.com" in documentation to "libpng.org" + Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). + Changed type of "params" from voidp to png_voidp in png_read|write_png(). + Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. + Revised the 3 instances of WRITEFILE in pngtest.c. + Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. + Updated png.rc in dll/msvc project + Revised makefile.dec to define and use LIBPATH and INCPATH + Increased size of global png_libpng_ver[] array from 12 to 18 chars. + Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. + Removed duplicate png_crc_finish() from png_handle_bKGD() function. + Added a warning when application calls png_read_update_info() multiple times. + Revised makefile.cygwin + Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. + Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). + +Version 1.0.9beta2 [November 19, 2000] + Renamed the "dll" subdirectory "projects". + Added borland project files to "projects" subdirectory. + Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. + Add error message in png_set_compression_buffer_size() when malloc fails. + +Version 1.0.9beta3 [November 23, 2000] + Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. + Removed the png_flush() in pngwrite.c that crashes some applications + that don't set png_output_flush_fn. + Added makefile.macosx and makefile.aix to scripts directory. + +Version 1.0.9beta4 [December 1, 2000] + Change png_chunk_warning to png_warning in png_check_keyword(). + Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). + +Version 1.0.9beta5 [December 15, 2000] + Added support for filter method 64 (for PNG datastreams embedded in MNG). + +Version 1.0.9beta6 [December 18, 2000] + Revised png_set_filter() to accept filter method 64 when appropriate. + Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to + help prevent applications from using MNG features in PNG datastreams. + Added png_permit_mng_features() function. + Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". + +Version 1.0.9rc1 [December 23, 2000] + Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c + Fixed error handling of unknown compression type in png_decompress_chunk(). + In pngconf.h, define __cdecl when _MSC_VER is defined. + +Version 1.0.9beta7 [December 28, 2000] + Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. + Revised memory management in png_set_hIST and png_handle_hIST in a backward + compatible manner. PLTE and tRNS were revised similarly. + Revised the iCCP chunk reader to ignore trailing garbage. + +Version 1.0.9beta8 [January 12, 2001] + Moved pngasmrd.h into pngconf.h. + Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. + +Version 1.0.9beta9 [January 15, 2001] + Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to + wince and msvc project module definition files. + Minor revision of makefile.cygwin. + Fixed bug with progressive reading of narrow interlaced images in pngpread.c + +Version 1.0.9beta10 [January 16, 2001] + Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. + Fixed "png_mmx_supported" typo in project definition files. + +Version 1.0.9beta11 [January 19, 2001] + Updated makefile.sgi to make shared library. + Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED + by default, for the benefit of DLL forward compatibility. These will + be re-enabled in version 1.2.0. + +Version 1.0.9rc2 [January 22, 2001] + Revised cygwin support. + +Version 1.0.9 [January 31, 2001] + Added check of cygwin's ALL_STATIC in pngconf.h + Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. + +Version 1.0.10beta1 [March 14, 2001] + Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. + Reformatted libpng.3 to eliminate bad line breaks. + Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c + Added prototype for png_mmx_support() near the top of pnggccrd.c + Moved some error checking from png_handle_IHDR to png_set_IHDR. + Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. + Revised png_mmx_support() function in pnggccrd.c + Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c + Fixed memory leak in contrib/visupng/PngFile.c + Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) + Added warnings when retrieving or setting gamma=0. + Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). + +Version 1.0.10rc1 [March 23, 2001] + Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, + and png_strlen. + Revised png_mmx_supported() function in pnggccrd.c to return proper value. + Fixed bug in progressive reading (pngpread.c) with small images (height < 8). + +Version 1.0.10 [March 30, 2001] + Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin + Added beos project files (Chris Herborth) + +Version 1.0.11beta1 [April 3, 2001] + Added type casts on several png_malloc() calls (Dimitri Papadapoulos). + Removed a no-longer needed AIX work-around from pngconf.h + Changed several "//" single-line comments to C-style in pnggccrd.c + +Version 1.0.11beta2 [April 11, 2001] + Removed PNGAPI from several functions whose prototypes did not have PNGAPI. + Updated scripts/pngos2.def + +Version 1.0.11beta3 [April 14, 2001] + Added checking the results of many instances of png_malloc() for NULL + +Version 1.0.11beta4 [April 20, 2001] + Undid the changes from version 1.0.11beta3. Added a check for NULL return + from user's malloc_fn(). + Removed some useless type casts of the NULL pointer. + Added makefile.netbsd + +Version 1.0.11 [April 27, 2001] + Revised makefile.netbsd + +Version 1.0.12beta1 [May 14, 2001] + Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) + Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h + Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. + Eliminated the png_error about apps using png_read|write_init(). Instead, + libpng will reallocate the png_struct and info_struct if they are too small. + This retains future binary compatibility for old applications written for + libpng-0.88 and earlier. + +Version 1.2.0beta1 [May 6, 2001] + Bumped DLLNUM to 2. + Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED + by default. + Added runtime selection of MMX features. + Added png_set_strip_error_numbers function and related macros. + +Version 1.2.0beta2 [May 7, 2001] + Finished merging 1.2.0beta1 with version 1.0.11 + Added a check for attempts to read or write PLTE in grayscale PNG datastreams. + +Version 1.2.0beta3 [May 17, 2001] + Enabled user memory function by default. + Modified png_create_struct so it passes user mem_ptr to user memory allocator. + Increased png_mng_features flag from png_byte to png_uint_32. + Bumped shared-library (so-number) and dll-number to 3. + +Version 1.2.0beta4 [June 23, 2001] + Check for missing profile length field in iCCP chunk and free chunk_data + in case of truncated iCCP chunk. + Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc + Bumped dll-number from 2 to 3 in makefile.cygwin + Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly + if user attempts to run it on an 8-bit display. + Updated contrib/gregbook + Use png_malloc instead of png_zalloc to allocate palette in pngset.c + Updated makefile.ibmc + Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes + of png_write_oFFS width and height from png_uint_32 to png_int_32. + Updated example.c + Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c + +Version 1.2.0beta5 [August 8, 2001] + Revised contrib/gregbook + Revised makefile.gcmmx + Revised pnggccrd.c to conditionally compile some thread-unsafe code only + when PNG_THREAD_UNSAFE_OK is defined. + Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with + value exceeding 2^bit_depth-1 + Revised makefile.sgi and makefile.sggcc + Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c + Removed restriction that do_invert_mono only operate on 1-bit opaque files + +Version 1.2.0 [September 1, 2001] + Changed a png_warning() to png_debug() in pnggccrd.c + Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). + +Version 1.2.1beta1 [October 19, 2001] + Revised makefile.std in contrib/pngminus + Include background_1 in png_struct regardless of gamma support. + Revised makefile.netbsd and makefile.macosx, added makefile.darwin. + Revised example.c to provide more details about using row_callback(). + +Version 1.2.1beta2 [October 25, 2001] + Added type cast to each NULL appearing in a function call, except for + WINCE functions. + Added makefile.so9. + +Version 1.2.1beta3 [October 27, 2001] + Removed type casts from all NULLs. + Simplified png_create_struct_2(). + +Version 1.2.1beta4 [November 7, 2001] + Revised png_create_info_struct() and png_creat_struct_2(). + Added error message if png_write_info() was omitted. + Type cast NULLs appearing in function calls when _NO_PROTO or + PNG_TYPECAST_NULL is defined. + +Version 1.2.1rc1 [November 24, 2001] + Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL + is defined. + Changed typecast of "size" argument to png_size_t in pngmem.c calls to + the user malloc_fn, to agree with the prototype in png.h + Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) + Updated makefile.sgi to recognize LIBPATH and INCPATH. + Updated various makefiles so "make clean" does not remove previous major + version of the shared library. + +Version 1.2.1rc2 [December 4, 2001] + Always allocate 256-entry internal palette, hist, and trans arrays, to + avoid out-of-bounds memory reference caused by invalid PNG datastreams. + Added a check for prefix_length > data_length in iCCP chunk handler. + +Version 1.2.1 [December 7, 2001] + None. + +Version 1.2.2beta1 [February 22, 2002] + Fixed a bug with reading the length of iCCP profiles (Larry Reeves). + Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate + libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h + Revised makefile.darwin to remove "-undefined suppress" option. + Added checks for gamma and chromaticity values over 21474.83, which exceed + the limit for PNG unsigned 32-bit integers when encoded. + Revised calls to png_create_read_struct() and png_create_write_struct() + for simpler debugging. + Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) + +Version 1.2.2beta2 [February 23, 2002] + Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. + Check for invalid image dimensions in png_get_IHDR. + Added missing "fi;" in the install target of the SGI makefiles. + Added install-static to all makefiles that make shared libraries. + Always do gamma compensation when image is partially transparent. + +Version 1.2.2beta3 [March 7, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later. + Modified shared-library makefiles to install pkgconfig/libpngNN.pc. + Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown + Removed unused png_write_destroy_info prototype from png.h + Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case + Added install-shared target to all makefiles that make shared libraries. + Stopped a double free of palette, hist, and trans when not using free_me. + Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. + +Version 1.2.2beta4 [March 8, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later (Jason Summers). + Relocated a misplaced /bin/rm in the "install-shared" makefile targets + Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. + +Version 1.2.2beta5 [March 26, 2002] + Added missing PNGAPI to several function definitions. + Check for invalid bit_depth or color_type in png_get_IHDR(), and + check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). + Revised iTXt support to accept NULL for lang and lang_key. + Compute gamma for color components of background even when color_type is gray. + Changed "()" to "{}" in scripts/libpng.pc.in. + Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN + Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so + +Version 1.2.2beta6 [March 31, 2002] + +Version 1.0.13beta1 [March 31, 2002] + Prevent png_zalloc() from trying to memset memory that it failed to acquire. + Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). + Ensure that the right function (user or default) is used to free the + png_struct after an error in png_create_read_struct_2(). + +Version 1.2.2rc1 [April 7, 2002] + +Version 1.0.13rc1 [April 7, 2002] + Save the ebx register in pnggccrd.c (Sami Farin) + Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). + Updated makefiles to put headers in include/libpng and remove old include/*.h. + +Version 1.2.2 [April 15, 2002] + +Version 1.0.13 [April 15, 2002] + Revised description of png_set_filter() in libpng.3/libpng.txt. + Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd + +Version 1.0.13patch01 [April 17, 2002] + +Version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and + makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to + install + Added install: target to makefile.32sunu and makefile.64sunu + +Version 1.0.13patch03 [April 18, 2002] + +Version 1.2.2patch03 [April 18, 2002] + Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng + subdirectory to libpngNN subdirectory without the full pathname. + Moved generation of libpng.pc from "install" to "all" in 15 makefiles. + +Version 1.2.3rc1 [April 28, 2002] + Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). + Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) + Fixed bug with $prefix, should be $(prefix) in makefile.hpux. + Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin + Added a link from libpngNN.pc to libpng.pc in 15 makefiles. + Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. + Revised makefile.darwin to make relative links without full pathname. + Added setjmp() at the end of png_create_*_struct_2() in case user forgets + to put one in their application. + Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and + removed them from module definition files. + +Version 1.2.3rc2 [May 1, 2002] + Fixed bug in reporting number of channels in pngget.c and pngset.c, + that was introduced in version 1.2.2beta5. + Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), + png_default_flush(), and png_push_fill_buffer() and included them in + module definition files. + Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. + +Version 1.2.3rc3 [May 1, 2002] + Revised prototype for png_default_flush() + Remove old libpng.pc and libpngNN.pc before installing new ones. + +Version 1.2.3rc4 [May 2, 2002] + Typos in *.def files (png_default_read|write -> png_default_read|write_data) + In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc + Added libpng-config and libpngNN-config and modified makefiles to install + them. + Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles + Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp + +Version 1.2.3rc5 [May 11, 2002] + Changed "error" and "message" in prototypes to "error_message" and + "warning_message" to avoid namespace conflict. + Revised 15 makefiles to build libpng-config from libpng-config-*.in + Once more restored png_zalloc and png_zfree to regular nonexported form. + Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer + to nonexported form, but with PNGAPI, and removed them from module def + files. + +Version 1.2.3rc6 [May 14, 2002] + Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c + Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. + Removed leftover libpng-config "sed" script from four makefiles. + Revised libpng-config creating script in 16 makefiles. + +Version 1.2.3 [May 22, 2002] + Revised libpng-config target in makefile.cygwin. + Removed description of png_set_mem_fn() from documentation. + Revised makefile.freebsd. + Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). + Revised projects/msvc/README.txt + Changed -lpng to -lpngNN in LDFLAGS in several makefiles. + +Version 1.2.4beta1 [May 24, 2002] + Added libpng.pc and libpng-config to "all:" target in 16 makefiles. + Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) + Added missing "\" before closing double quote in makefile.gcmmx. + Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() + functions. + +Version 1.2.4beta2 [June 25, 2002] + Plugged memory leak of png_ptr->current_text (Matt Holgate). + Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) + Added -soname to the loader flags in makefile.dec, makefile.sgi, and + makefile.sggcc. + Added "test-installed" target to makefile.linux, makefile.gcmmx, + makefile.sgi, and makefile.sggcc. + +Version 1.2.4beta3 [June 28, 2002] + Plugged memory leak of row_buf in pngtest.c when there is a png_error(). + Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. + Added "test-installed" target to makefile.32sunu, makefile.64sunu, + makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, + makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. + +Version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + Added "test-installed" target to makefile.cygwin and makefile.sco. + Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. + +Version 1.2.4 and 1.0.14 [July 8, 2002] + Changed png_warning() to png_error() when width is too large to process. + +Version 1.2.4patch01 [July 20, 2002] + Revised makefile.cygwin to use DLL number 12 instead of 13. + +Version 1.2.5beta1 [August 6, 2002] + Added code to contrib/gregbook/readpng2.c to ignore unused chunks. + Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) + Removed some stray *.o files from contrib/gregbook. + Changed png_error() to png_warning() about "Too much data" in pngpread.c + and about "Extra compressed data" in pngrutil.c. + Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). + Updated makefile.hpgcc + Updated png.c and pnggccrd.c handling of return from png_mmx_support() + +Version 1.2.5beta2 [August 15, 2002] + Only issue png_warning() about "Too much data" in pngpread.c when avail_in + is nonzero. + Updated makefiles to install a separate libpng.so.3 with its own rpath. + +Version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + Revised makefiles to not remove previous minor versions of shared libraries. + +Version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared + library loader directive. + Added missing "$OBJSDLL" line to makefile.gcmmx. + Added missing "; fi" to makefile.32sunu. + +Version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + Revised libpng-config script. + +Version 1.2.5 and 1.0.15 [October 3, 2002] + Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, + and makefile.aix. + Relocated two misplaced PNGAPI lines in pngtest.c + +Version 1.2.6beta1 [October 22, 2002] + Commented out warning about uninitialized mmx_support in pnggccrd.c. + Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. + Relocated two more misplaced PNGAPI lines in pngtest.c + Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, + introduced in version 1.0.2. + Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. + +Version 1.2.6beta2 [November 1, 2002] + Added libpng-config "--ldopts" output. + Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" + in makefiles. + +Version 1.2.6beta3 [July 18, 2004] + Reverted makefile changes from version 1.2.6beta2 and some of the changes + from version 1.2.6beta1; these will be postponed until version 1.2.7. + Version 1.2.6 is going to be a simple bugfix release. + Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. + Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. + Added "#!/bin/sh" at the top of configure, for recognition of the + 'x' flag under Cygwin (Cosmin). + Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). + Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). + Fixed the special memory handler for Borland C under DOS, in pngmem.c + (Cosmin). + Removed some spurious assignments in pngrutil.c (Cosmin). + Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings + on 16-bit platforms (Cosmin). + Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). + Used proper type png_fixed_point, to avoid problems on 16-bit platforms, + in png_handle_sRGB() (Cosmin). + Added compression_type to png_struct, and optimized the window size + inside the deflate stream (Cosmin). + Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). + Fixed handling of unknown chunks that come after IDAT (Cosmin). + Allowed png_error() and png_warning() to work even if png_ptr == NULL + (Cosmin). + Replaced row_info->rowbytes with row_bytes in png_write_find_filter() + (Cosmin). + Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). + Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded + values in png.c (Simon-Pierre, Cosmin). + Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). + Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc + (Simon-Pierre). + Moved the definition of PNG_HEADER_VERSION_STRING near the definitions + of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). + Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). + Updated scripts/makefile.vc(a)win32 (Cosmin). + Updated the MSVC project (Simon-Pierre, Cosmin). + Updated the Borland C++ Builder project (Cosmin). + Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). + Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). + Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). + Added extra guard around inclusion of Turbo C memory headers, in pngconf.h + (Cosmin). + Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to + projects/cbuilder5/ (Cosmin). + Moved projects/visualc6/png32ms.def to scripts/pngw32.def, + and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). + Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). + Changed line endings to DOS style in cbuilder5 and visualc6 files, even + in the tar.* distributions (Cosmin). + Updated contrib/visupng/VisualPng.dsp (Cosmin). + Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). + Added a separate distribution with "configure" and supporting files (Junichi). + +Version 1.2.6beta4 [July 28, 2004] + Added user ability to change png_size_t via a PNG_SIZE_T macro. + Added png_sizeof() and png_convert_size() functions. + Added PNG_SIZE_MAX (maximum value of a png_size_t variable. + Added check in png_malloc_default() for (size_t)size != (png_uint_32)size + which would indicate an overflow. + Changed sPLT failure action from png_error to png_warning and abandon chunk. + Changed sCAL and iCCP failures from png_error to png_warning and abandon. + Added png_get_uint_31(png_ptr, buf) function. + Added PNG_UINT_32_MAX macro. + Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. + Made png_zalloc() issue a png_warning and return NULL on potential + overflow. + Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x + Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. + Revised Borland portion of png_malloc() to return NULL or issue + png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. + Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove + sequential read support. + Added some "#if PNG_WRITE_SUPPORTED" blocks. + Added #ifdef to remove some redundancy in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the pallete. + +Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability in png_handle_tRNS() + Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed some harmless bugs in png_handle_sBIT, etc, that would cause + duplicate chunk types to go undetected. + Fixed some timestamps in the -config version + Rearranged order of processing of color types in png_handle_tRNS(). + Added ROWBYTES macro to calculate rowbytes without integer overflow. + Updated makefile.darwin and removed makefile.macosx from scripts directory. + Imposed default one million column, one-million row limits on the image + dimensions, and added png_set_user_limits() function to override them. + Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. + Fixed wrong cast of returns from png_get_user_width|height_max(). + Changed some "keep the compiler happy" from empty statements to returns, + Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution + +Version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. + Revised pngtest's png_debug_malloc() to use png_malloc() instead of + png_malloc_default() which is not supposed to be exported. + Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in + pngpread.c. Bug was introduced in 1.2.6rc1. + Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. + Fixed old bug in RGB to Gray transformation. + Fixed problem with 64-bit compilers by casting arguments to abs() + to png_int_32. + Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). + Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) + Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. + Added code to update the row_info->colortype in png_do_read_filler() (MSB). + +Version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid + trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. + Revised documentation of png_set_keep_unknown_chunks(). + Check handle_as_unknown status in pngpread.c, as in pngread.c previously. + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h + Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c + +Version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of + "pinfo" was out of place). + +Version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +Version 1.2.6 and 1.0.16 [August 15, 2004] + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. + +Version 1.2.7beta1 [August 26, 2004] + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. + +Version 1.2.7beta2 [August 28, 2004] + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6rc2 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. + +Version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. + +Version 1.2.7 and 1.0.17 [September 12, 2004] + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin + +Version 1.2.8beta1 [November 1, 2004] + Fixed bug in png_text_compress() that would fail to complete a large block. + Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during + strip alpha operation in png_do_strip_filler(). + Added PNG_1_2_X definition in pngconf.h + Use #ifdef to comment out png_info_init in png.c and png_read_init in + pngread.c (as of 1.3.0) + +Version 1.2.8beta2 [November 2, 2004] + Reduce color_type to a nonalpha type after strip alpha operation in + png_do_strip_filler(). + +Version 1.2.8beta3 [November 3, 2004] + Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM + +Version 1.2.8beta4 [November 12, 2004] + Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). + Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). + Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection + of data type in deflate (Cosmin). + Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. + +Version 1.2.8beta5 [November 20, 2004] + Use png_ptr->flags instead of png_ptr->transformations to pass + PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI + compatibility. + Revised handling of SPECIALBUILD, PRIVATEBUILD, + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. + +Version 1.2.8rc1 [November 24, 2004] + Moved handling of BUILD macros from pngconf.h to png.h + Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently + omitted from beta5. + Revised scripts/pngw32.rc + Despammed mailing addresses by masking "@" with "at". + Inadvertently installed a supposedly faster test version of pngrutil.c + +Version 1.2.8rc2 [November 26, 2004] + Added two missing "\" in png.h + Change tests in pngread.c and pngpread.c to + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +Version 1.2.8rc3 [November 28, 2004] + Reverted pngrutil.c to version libpng-1.2.8beta5. + Added scripts/makefile.elf with supporting code in pngconf.h for symbol + versioning (John Bowler). + +Version 1.2.8rc4 [November 29, 2004] + Added projects/visualc7 (Simon-pierre). + +Version 1.2.8rc5 [November 29, 2004] + Fixed new typo in scripts/pngw32.rc + +Version 1.2.8 [December 3, 2004] + Removed projects/visualc7, added projects/visualc71. + +Version 1.2.9beta1 [February 21, 2006] + Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints + Revised man page and libpng.txt to make it clear that one should not call + png_read_end or png_write_end after png_read_png or png_write_png. + Updated references to png-mng-implement mailing list. + Fixed an incorrect typecast in pngrutil.c + Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. + Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. + Optimized alpha-inversion loops in pngwtran.c + Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c + Make sure num_trans is <= 256 before copying data in png_set_tRNS(). + Make sure num_palette is <= 256 before copying data in png_set_PLTE(). + Interchanged order of write_swap_alpha and write_invert_alpha transforms. + Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). + Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). + Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). + Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, + png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). + Added type cast (png_byte) in png_write_sCAL() (Cosmin). + Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). + Default iTXt support was inadvertently enabled. + +Version 1.2.9beta2 [February 21, 2006] + Check for png_rgb_to_gray and png_gray_to_rgb read transformations before + checking for png_read_dither in pngrtran.c + Revised checking of chromaticity limits to accommodate extended RGB + colorspace (John Denker). + Changed line endings in some of the project files to CRLF, even in the + "Unix" tar distributions (Cosmin). + Made png_get_int_32 and png_save_int_32 always available (Cosmin). + Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def + with the newly exported functions. + Eliminated distributions without the "configure" script. + Updated INSTALL instructions. + +Version 1.2.9beta3 [February 24, 2006] + Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp + Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) + Removed reference to pngasmrd.h from Makefile.am + Renamed CHANGES to ChangeLog. + Renamed LICENSE to COPYING. + Renamed ANNOUNCE to NEWS. + Created AUTHORS file. + +Version 1.2.9beta4 [March 3, 2006] + Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac + Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. + Removed newline from the end of some error and warning messages. + Removed test for sqrt() from configure.ac and configure. + Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). + Disabled default iTXt support that was inadvertently enabled in + libpng-1.2.9beta1. + Added "OS2" to list of systems that don't need underscores, in pnggccrd.c + Removed libpng version and date from *.c files. + +Version 1.2.9beta5 [March 4, 2006] + Removed trailing blanks from source files. + Put version and date of latest change in each source file, and changed + copyright year accordingly. + More cleanup of configure.ac, Makefile.am, and associated scripts. + Restored scripts/makefile.elf which was inadvertently deleted. + +Version 1.2.9beta6 [March 6, 2006] + Fixed typo (RELEASE) in configuration files. + +Version 1.2.9beta7 [March 7, 2006] + Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am + Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() + in png.h. + Updated makefile.elf as suggested by debian. + Made cosmetic changes to some makefiles, adding LN_SF and other macros. + Made some makefiles accept "exec_prefix". + +Version 1.2.9beta8 [March 9, 2006] + Fixed some "#if defined (..." which should be "#if defined(..." + Bug introduced in libpng-1.2.8. + Fixed inconsistency in definition of png_default_read_data() + Restored blank that was lost from makefile.sggcc "clean" target in beta7. + Revised calculation of "current" and "major" for irix in ltmain.sh + Changed "mkdir" to "MKDIR_P" in some makefiles. + Separated PNG_EXPAND and PNG_EXPAND_tRNS. + Added png_set_expand_gray_1_2_4_to_8() and deprecated + png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. + +Version 1.2.9beta9 [March 10, 2006] + Include "config.h" in pngconf.h when available. + Added some checks for NULL png_ptr or NULL info_ptr (timeless) + +Version 1.2.9beta10 [March 20, 2006] + Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) + Made pnggccrd.c PIC-compliant (Christian Aichinger). + Added makefile.mingw (Wolfgang Glas). + Revised pngconf.h MMX checking. + +Version 1.2.9beta11 [March 22, 2006] + Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 + Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. + +Version 1.2.9rc1 [March 31, 2006] + Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). + Removed nonsensical assertion check from pngtest.c (Cosmin). + +Version 1.2.9 [April 14, 2006] + Revised makefile.beos and added "none" selector in ltmain.sh + +Version 1.2.10beta1 [April 15, 2006] + Renamed "config.h" to "png_conf.h" and revised Makefile.am to add + -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h + to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. + +Version 1.2.10beta2 [April 15, 2006] + Manually updated Makefile.in and configure. Changed png_conf.h.in + back to config.h. + +Version 1.2.10beta3 [April 15, 2006] + Change png_conf.h back to config.h in pngconf.h. + +Version 1.2.10beta4 [April 16, 2006] + Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. + +Version 1.2.10beta5 [April 16, 2006] + Added a configure check for compiling assembler code in pnggccrd.c + +Version 1.2.10beta6 [April 17, 2006] + Revised the configure check for pnggccrd.c + Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ + Added @LIBPNG_DEFINES@ to arguments when building libpng.sym + +Version 1.2.10beta7 [April 18, 2006] + Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. + +Version 1.2.10rc1 [April 19, 2006] + Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD + Fixed "LN_FS" typo in makefile.sco and makefile.solaris. + +Version 1.2.10rc2 [April 20, 2006] + Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE + in configure.ac and configure + Made the configure warning about versioned symbols less arrogant. + +Version 1.2.10rc3 [April 21, 2006] + Added a note in libpng.txt that png_set_sig_bytes(8) can be used when + writing an embedded PNG without the 8-byte signature. + Revised makefiles and configure to avoid making links to libpng.so.* + +Version 1.2.10 [April 23, 2006] + Reverted configure to "rc2" state. + +Version 1.2.11beta1 [May 31, 2006] + scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + The shared-library makefiles were linking to libpng.so.0 instead of + libpng.so.3 compatibility as the library. + +Version 1.2.11beta2 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) + +Version 1.2.11beta3 [June 5, 2006] + Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). + Removed the accidental leftover Makefile.in~ (Cosmin). + Avoided potential buffer overflow and optimized buffer in + png_write_sCAL(), png_write_sCAL_s() (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). + +Version 1.2.11beta4 [June 6, 2006] + Allow zero-length IDAT chunks after the entire zlib datastream, but not + after another intervening chunk type. + +Version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] + Deleted extraneous square brackets from [config.h] in configure.ac + +Version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] + Added prototypes for PNG_INCH_CONVERSIONS functions to png.h + Revised INSTALL and autogen.sh + Fixed typo in several makefiles (-W1 should be -Wl) + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + +Version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] + Removed the new typedefs for 64-bit systems (delay until version 1.4.0) + Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid + reading out of bounds. + +Version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] + Really removed the new typedefs for 64-bit systems. + +Version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] + Removed png_sig_bytes entry from scripts/pngw32.def + +Version 1.0.19, 1.2.11 [June 26, 2006] + None. + +Version 1.0.20, 1.2.12 [June 27, 2006] + Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + +Version 1.2.13beta1 [October 2, 2006] + Removed AC_FUNC_MALLOC from configure.ac + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Change "logical" to "bitwise" throughout documentation. + Detect and fix attempt to write wrong iCCP profile length. + +Version 1.0.21, 1.2.13 [November 14, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + Check all exported functions for NULL png_ptr. + +Version 1.2.14beta1 [November 17, 2006] + Relocated three misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + +Version 1.2.14beta2 [November 17, 2006] + Added some typecasts in png_zalloc(). + +Version 1.2.14rc1 [November 20, 2006] + Changed "strtod" to "png_strtod" in pngrutil.c + +Version 1.0.22, 1.2.14 [November 27, 2006] + Added missing "$(srcdir)" in Makefile.am and Makefile.in + +Version 1.2.15beta1 [December 3, 2006] + Generated configure with autoconf-2.61 instead of 2.60 + Revised configure.ac to update libpng.pc and libpng-config. + +Version 1.2.15beta2 [December 3, 2006] + Always export MMX asm functions, just stubs if not building pnggccrd.c + +Version 1.2.15beta3 [December 4, 2006] + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +Version 1.2.15beta4 [December 7, 2006] + Added scripts/CMakeLists.txt + Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta + +Version 1.2.15beta5 [December 7, 2006] + Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c + Revised scripts/CMakeLists.txt + +Version 1.2.15beta6 [December 13, 2006] + Revised scripts/CMakeLists.txt and configure.ac + +Version 1.2.15rc1 [December 18, 2006] + Revised scripts/CMakeLists.txt + +Version 1.2.15rc2 [December 21, 2006] + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.2.15rc3 [December 25, 2006] + Fixed shared library numbering error that was introduced in 1.2.15beta6. + +Version 1.2.15rc4 [December 27, 2006] + Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. + +Version 1.2.15rc5 [December 31, 2006] + Revised handling of rgb_to_gray. + +Version 1.2.15 [January 5, 2007] + Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. + +Version 1.2.16beta1 [January 6, 2007] + Fix bugs in makefile.nommx + +Version 1.2.16beta2 [January 16, 2007] + Revised scripts/CMakeLists.txt + +Version 1.2.16 [January 31, 2007] + No changes. + +Version 1.2.17beta1 [March 6, 2007] + Revised scripts/CMakeLists.txt to install both shared and static libraries. + Deleted a redundant line from pngset.c. + +Version 1.2.17beta2 [April 26, 2007] + Relocated misplaced test for png_ptr == NULL in pngpread.c + Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN + flags. + Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* + Added pngerror() when write_IHDR fails in deflateInit2(). + Added "const" to some array declarations. + Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. + +Version 1.2.17rc1 [May 4, 2007] + No changes. + +Version 1.2.17rc2 [May 8, 2007] + Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications + calling set_unknown_chunk_location() need them. + Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in + png_set_expand_gray_1_2_4_to_8(). + Added png_ptr->unknown_chunk to hold working unknown chunk data, so it + can be free'ed in case of error. Revised unknown chunk handling in + pngrutil.c and pngpread.c to use this structure. + +Version 1.2.17rc3 [May 8, 2007] + Revised symbol-handling in configure script. + +Version 1.2.17rc4 [May 10, 2007] + Revised unknown chunk handling to avoid storing unknown critical chunks. + +Version 1.0.25 [May 15, 2007] +Version 1.2.17 [May 15, 2007] + Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, + to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) + +Version 1.0.26 [May 15, 2007] +Version 1.2.18 [May 15, 2007] + Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script + +Version 1.2.19beta1 [May 18, 2007] + Changed "const static" to "static PNG_CONST" everywhere, mostly undoing + change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" + Changed some handling of unused parameters, to avoid compiler warnings. + "if (unused == NULL) return;" becomes "unused = unused". + +Version 1.2.19beta2 [May 18, 2007] + Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) + +Version 1.2.19beta3 [May 19, 2007] + Add some "png_byte" typecasts in png_check_keyword() and write new_key + instead of key in zTXt chunk (Kevin Ryde). + +Version 1.2.19beta4 [May 21, 2007] + Add png_snprintf() function and use it in place of sprint() for improved + defense against buffer overflows. + +Version 1.2.19beta5 [May 21, 2007] + Fixed png_handle_tRNS() to only use the valid bits of tRNS value. + Changed handling of more unused parameters, to avoid compiler warnings. + Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. + +Version 1.2.19beta6 [May 22, 2007] + Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c + Added a special "_MSC_VER" case that defines png_snprintf to _snprintf + +Version 1.2.19beta7 [May 22, 2007] + Squelched png_squelch_warnings() in pnggccrd.c and added + an #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused + the warnings that png_squelch_warnings was squelching. + +Version 1.2.19beta8 [May 22, 2007] + Removed __MMX__ from test in pngconf.h. + +Version 1.2.19beta9 [May 23, 2007] + Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. + Revised png_squelch_warnings() so it might work. + Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. + +Version 1.2.19beta10 [May 24, 2007] + Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. + +Version 1.4.0beta1 [April 20, 2006] + Enabled iTXt support (changes png_struct, thus requires so-number change). + Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED + Eliminated PNG_1_0_X and PNG_1_2_X macros. + Removed deprecated functions png_read_init, png_write_init, png_info_init, + png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and + removed the deprecated macro PNG_MAX_UINT. + Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h + Removed many WIN32_WCE #ifdefs (Cosmin). + Reduced dependency on C-runtime library when on Windows (Simon-Pierre) + Replaced sprintf() with png_sprintf() (Simon-Pierre) + +Version 1.4.0beta2 [April 20, 2006] + Revised makefiles and configure to avoid making links to libpng.so.* + Moved some leftover MMX-related defines from pngconf.h to pngintrn.h + Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def + +Version 1.4.0beta3 [May 10, 2006] + Updated scripts/pngw32.def to comment out MMX functions. + Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. + Scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + Revised pngconf.h and added pngconf.h.in, so makefiles and configure can + pass defines to libpng and applications. + +Version 1.4.0beta4 [May 11, 2006] + Revised configure.ac, Makefile.am, and many of the makefiles to write + their defines in pngconf.h. + +Version 1.4.0beta5 [May 15, 2006] + Added a missing semicolon in Makefile.am and Makefile.in + Deleted extraneous square brackets from configure.ac + +Version 1.4.0beta6 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Changed sonum from 0 to 1. + Removed unused prototype for png_check_sig() from png.h + +Version 1.4.0beta7 [June 16, 2006] + Exported png_write_sig (Cosmin). + Optimized buffer in png_handle_cHRM() (Cosmin). + Set pHYs = 2835 x 2835 pixels per meter, and added + sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). + Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. + +Version 1.4.0beta8 [June 22, 2006] + Added demonstration of user chunk support in pngtest.c, to support the + public sTER chunk and a private vpAg chunk. + +Version 1.4.0beta9 [July 3, 2006] + Removed ordinals from scripts/pngw32.def and removed png_info_int and + png_set_gray_1_2_4_to_8 entries. + Inline call of png_get_uint_32() in png_get_uint_31(). + Use png_get_uint_31() to get vpAg width and height in pngtest.c + Removed WINCE and Netware projects. + Removed standalone Y2KINFO file. + +Version 1.4.0beta10 [July 12, 2006] + Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and + some makefiles, because it was not working reliably. Instead, distribute + pngconf.h.in along with pngconf.h and cause configure and some of the + makefiles to update pngconf.h from pngconf.h.in. + Added pngconf.h to DEPENDENCIES in Makefile.am + +Version 1.4.0beta11 [August 19, 2006] + Removed AC_FUNC_MALLOC from configure.ac. + Added a warning when writing iCCP profile with mismatched profile length. + Patched pnggccrd.c to assemble on x86_64 platforms. + Moved chunk header reading into a separate function png_read_chunk_header() + in pngrutil.c. The chunk header (len+sig) is now serialized in a single + operation (Cosmin). + Implemented support for I/O states. Added png_ptr member io_state, and + functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + (Cosmin). + Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). + Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Cosmin). + Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). + Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). + Added pngintrn.h to the Visual C++ projects (Cosmin). + Removed scripts/list (Cosmin). + Updated copyright year in scripts/pngwin.def (Cosmin). + Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). + Disallowed the user to redefine png_size_t, and enforced a consistent use + of png_size_t across libpng (Cosmin). + Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends + to png_size_t (Cosmin). + Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). + Removed some unnecessary type casts (Cosmin). + Changed prototype of png_get_compression_buffer_size() and + png_set_compression_buffer_size() to work with png_size_t instead of + png_uint_32 (Cosmin). + Removed png_memcpy_check() and png_memset_check() (Cosmin). + Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). + Clarified that png_zalloc() does not clear the allocated memory, + and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). + Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in + pngconf.h, and used it in all memory allocation functions (Cosmin). + Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file + mentioning that the symbols declared in that file are private, and + updated the scripts and the Visual C++ projects accordingly (Cosmin). + Removed circular references between pngconf.h and pngconf.h.in in + scripts/makefile.vc*win32 (Cosmin). + Removing trailing '.' from the warning and error messages (Cosmin). + Added pngdefs.h that is built by makefile or configure, instead of + pngconf.h.in (Glenn). + Detect and fix attempt to write wrong iCCP profile length. + +Version 1.4.0beta12 [October 19, 2006] + Changed "logical" to "bitwise" in the documentation. + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Add a typecast to stifle compiler warning in pngrutil.c + +Version 1.4.0beta13 [November 10, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + +Version 1.4.0beta14 [November 15, 2006] + Check all exported functions for NULL png_ptr. + +Version 1.4.0beta15 [November 17, 2006] + Relocated two misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + Add "install: all" in Makefile.am so "configure; make install" will work. + +Version 1.4.0beta16 [November 17, 2006] + Added a typecast in png_zalloc(). + +Version 1.4.0beta17 [December 4, 2006] + Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +Version 1.4.0beta18 [December 7, 2006] + Added scripts/CMakeLists.txt + +Version 1.4.0beta19 [May 16, 2007] + Revised scripts/CMakeLists.txt + Rebuilt configure and Makefile.in with newer tools. + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.4.0beta20 [July 9, 2008] + Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications + calling set_unknown_chunk_location() need them. + Moved several macro definitions from pngpriv.h to pngconf.h + Merge with changes to the 1.2.X branch, as of 1.2.30beta04. + Deleted all use of the MMX assembler code and Intel-licensed optimizations. + Revised makefile.mingw + +Version 1.4.0beta21 [July 21, 2008] + Moved local array "chunkdata" from pngrutil.c to the png_struct, so + it will be freed by png_read_destroy() in case of a read error (Kurt + Christensen). + +Version 1.4.0beta22 [July 21, 2008] + Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. + +Version 1.4.0beta23 [July 22, 2008] + Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in + png_decompress_chunk(). + +Version 1.4.0beta24 [July 25, 2008] + Change all remaining "chunkdata" to "png_ptr->chunkdata" in + png_decompress_chunk(), and remove "chunkdata" from parameter list. + Put a call to png_check_chunk_name() in png_read_chunk_header(). + Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte. + Removed two calls to png_check_chunk_name() occuring later in the process. + Define PNG_NO_ERROR_NUMBERS by default in pngconf.h + +Version 1.4.0beta25 [July 30, 2008] + Added a call to png_check_chunk_name() in pngpread.c + Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte. + Added png_push_have_buffer() function to pngpread.c + Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. + Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. + Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. + Synced contrib directory and configure files with libpng-1.2.30beta06. + Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) + Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c + +Version 1.4.0beta26 [August 4, 2008] + Removed png_push_have_buffer() function in pngpread.c. It increased the + compiled library size slightly. + Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) + Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Added PNG_LITERAL_CHARACTER macros for #, [, and ]. + +Version 1.4.0beta27 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Moved newline character from individual png_debug messages into the + png_debug macros. + Allow user to #define their own png_debug, png_debug1, and png_debug2. + +Version 1.4.0beta28 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Added PNG_STRING_NEWLINE macro + +Version 1.4.0beta29 [August 9, 2008] + Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. + Added PNG_STRING_COPYRIGHT macro. + Added non-ISO versions of png_debug macros. + +Version 1.4.0beta30 [August 14, 2008] + Added premultiplied alpha feature (Volker Wiendl). + +Version 1.4.0beta31 [August 18, 2008] + Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c + Removed extra crc check at the end of png_handle_cHRM(). Bug introduced + in libpng-1.4.0beta20. + +Version 1.4.0beta32 [August 19, 2008] + Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + Revised PNG_NO_STDIO version of png_write_flush() + +Version 1.4.0beta33 [August 20, 2008] + Added png_get|set_chunk_cache_max() to limit the total number of sPLT, + text, and unknown chunks that can be stored. + +Version 1.4.0beta34 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c + Fixed off-by-one error introduced in png_push_read_zTXt() function in + libpng-1.2.30beta04/pngpread.c (Harald van Dijk) + +Version 1.4.0beta35 [October 6, 2008] + Changed "trans_values" to "trans_color". + Changed so-number from 0 to 14. Some OS do not like 0. + Revised makefile.darwin to fix shared library numbering. + Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8() + in example.c (debian bug report) + +Version 1.4.0beta36 [October 25, 2008] + Sync with tEXt vulnerability fix in libpng-1.2.33rc02. + +Version 1.4.0beta37 [November 13, 2008] + Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, + and pngwrite.c + +Version 1.4.0beta38 [November 22, 2008] + Added check for zero-area RGB cHRM triangle in png_check_cHRM() and + png_check_cHRM_fixed(). + +Version 1.4.0beta39 [November 23, 2008] + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. + +Version 1.4.0beta40 [November 24, 2008] + Eliminated png_check_cHRM(). Instead, always use png_check_cHRM_fixed(). + In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant + check for all-zero coordinates that is detected by the triangle check. + +Version 1.4.0beta41 [November 26, 2008] + Fixed string vs pointer-to-string error in png_check_keyword(). + Rearranged test expressions in png_check_cHRM_fixed() to avoid internal + overflows. + Added PNG_NO_CHECK_cHRM conditional. + +Version 1.4.0beta42, 43 [December 1, 2008] + Merge png_debug with version 1.2.34beta04. + +Version 1.4.0beta44 [December 6, 2008] + Removed redundant check for key==NULL before calling png_check_keyword() + to ensure that new_key gets initialized and removed extra warning + (Merge with version 1.2.34beta05 -- Arvan Pritchard). + +Version 1.4.0beta45 [December 9, 2008] + In png_write_png(), respect the placement of the filler bytes in an earlier + call to png_set_filler() (Jim Barry). + +Version 1.4.0beta46 [December 10, 2008] + Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and + PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated + PNG_TRANSFORM_STRIP_FILLER (Jim Barry). + +Version 1.4.0beta47 [December 15, 2008] + Support for dithering was disabled by default, because it has never + been well tested and doesn't work very well. The code has not + been removed, however, and can be enabled by building libpng with + PNG_READ_DITHER_SUPPORTED defined. + +Version 1.4.0beta48 [February 14, 2009] + Added new exported function png_calloc(). + Combined several instances of png_malloc(); png_memset() into png_calloc(). + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined. + +Version 1.4.0beta49 [February 28, 2009] + Added png_fileno() macro to pngconf.h, used in pngwio.c + Corrected order of #ifdef's in png_debug definition in png.h + Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments + for pcal_params. + Fixed order of #ifdef directives in the png_debug defines in png.h + (bug introduced in libpng-1.2.34/1.4.0beta29). + Revised comments in png_set_read_fn() and png_set_write_fn(). + +Version 1.4.0beta50 [March 18, 2009] + Use png_calloc() instead of png_malloc() to allocate big_row_buf when + reading an interlaced file, to avoid a possible UMR. + Undid revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined + or supply their own flush_fn() replacement. + Revised libpng*.txt and png.h documentation about use of png_write_flush() + and png_set_write_fn(). + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + +Version 1.4.0beta51 [March 21, 2009] + Removed new png_fileno() macro from pngconf.h . + +Version 1.4.0beta52 [March 27, 2009] + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt + +Version 1.4.0beta53 [April 1, 2009] + Removed some remaining MMX macros from pngpriv.h + Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) + +Version 1.4.0beta54 [April 13, 2009] + Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow + application code writers to bypass the check for multiple inclusion + of setjmp.h when they know that it is safe to ignore the situation. + Eliminated internal use of setjmp() in pngread.c and pngwrite.c + Reordered ancillary chunks in pngtest.png to be the same as what + pngtest now produces, and made some cosmetic changes to pngtest output. + Eliminated deprecated png_read_init_3() and png_write_init_3() functions. + +Version 1.4.0beta55 [April 15, 2009] + Simplified error handling in pngread.c and pngwrite.c by putting + the new png_read_cleanup() and png_write_cleanup() functions inline. + +Version 1.4.0beta56 [April 25, 2009] + Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress + "shadowed declaration" warning from gcc-4.3.3. + Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration" + warning about a global "gamma" variable in math.h on some platforms. + +Version 1.4.0beta57 [May 2, 2009] + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined (again). + Rebuilt configure scripts with autoconf-2.63 instead of 2.62 + Removed pngprefs.h and MMX from makefiles + +Version 1.4.0beta58 [May 14, 2009] + Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced + in beta57). + Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) + +Version 1.4.0beta59 [May 15, 2009] + Reformated sources in libpng style (3-space intentation, comment format) + Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) + Added sections about the git repository and our coding style to the + documentation + Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + +Version 1.4.0beta60 [May 19, 2009] + Conditionally compile png_read_finish_row() which is not used by + progressive readers. + Added contrib/pngminim/preader to demonstrate building minimal progressive + decoder, based on contrib/gregbook with embedded libpng and zlib. + +Version 1.4.0beta61 [May 20, 2009] + In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there + is only one makefile in those directories, and revised the README files + accordingly. + More reformatting of comments, mostly to capitalize sentences. + +Version 1.4.0beta62 [June 2, 2009] + Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h + and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h + Reformatted several remaining "else statement" into two lines. + Added a section to the libpng documentation about using png_get_io_ptr() + in configure scripts to detect the presence of libpng. + +Version 1.4.0beta63 [June 15, 2009] + Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR() + multiple times and to specify the sample order in the tRNS chunk, + because the ISO PNG specification has a typo in the tRNS table. + Changed several PNG_UNKNOWN_CHUNK_SUPPORTED to + PNG_HANDLE_AS_UNKNOWN_SUPPORTED, to make the png_set_keep mechanism + available for ignoring known chunks even when not saving unknown chunks. + Adopted preference for consistent use of "#ifdef" and "#ifndef" versus + "#if defined()" and "if !defined()" where possible. + +Version 1.4.0beta64 [June 24, 2009] + Eliminated PNG_LEGACY_SUPPORTED code. + Moved the various unknown chunk macro definitions outside of the + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + +Version 1.4.0beta65 [June 26, 2009] + Added a reference to the libpng license in each file. + +Version 1.4.0beta66 [June 27, 2009] + Refer to the libpng license instead of the libpng license in each file. + +Version 1.4.0beta67 [July 6, 2009] + Relocated INVERT_ALPHA within png_read_png() and png_write_png(). + Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. + Added an "xcode" project to the projects directory (Alam Arias). + +Version 1.4.0beta68 [July 19, 2009] + Avoid some tests in filter selection in pngwutil.c + +Version 1.4.0beta69 [July 25, 2009] + Simplified the new filter-selection test. This runs faster in the + common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. + Removed extraneous declaration from the new call to png_read_gray_to_rgb() + (bug introduced in libpng-1.4.0beta67). + Fixed up xcode project (Alam Arias) + Added a prototype for png_64bit_product() in png.c + +Version 1.4.0beta70 [July 27, 2009] + Avoid a possible NULL dereference in debug build, in png_set_text_2(). + (bug introduced in libpng-0.95, discovered by Evan Rouault) + +Version 1.4.0beta71 [July 29, 2009] + Rebuilt configure scripts with autoconf-2.64. + +Version 1.4.0beta72 [August 1, 2009] + Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec + from . + +Version 1.4.0beta73 [August 1, 2009] + Reject attempt to write iCCP chunk with negative embedded profile length + (JD Chen) + +Version 1.4.0beta74 [August 8, 2009] + Changed png_ptr and info_ptr member "trans" to "trans_alpha". + +Version 1.4.0beta75 [August 21, 2009] + Removed an extra png_debug() recently added to png_write_find_filter(). + Fixed incorrect #ifdef in pngset.c regarding unknown chunk support. + +Version 1.4.0beta76 [August 22, 2009] + Moved an incorrectly located test in png_read_row() in pngread.c + +Version 1.4.0beta77 [August 27, 2009] + Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, + and the "noconfig" files from the distribution. + Moved CMakeLists.txt from scripts into the main libpng directory. + Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) + +Version 1.4.0beta78 [August 31, 2009] + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. + Use png_malloc plus a loop instead of png_calloc() to initialize + row_pointers in png_read_png(). + +Version 1.4.0beta79 [September 1, 2009] + Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. + Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). + +Version 1.4.0beta80 [September 17, 2009] + Removed scripts/libpng.icc + Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). + (Dennis Gustafsson) + Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") + +Version 1.4.0beta81 [September 23, 2009] + Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h + Expanded TAB characters in pngrtran.c + Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid + compiler complaints about doubly declaring things "const". + Changed all "#if [!]defined(X)" to "if[n]def X" where possible. + Eliminated unused png_ptr->row_buf_size + +Version 1.4.0beta82 [September 25, 2009] + Moved redundant IHDR checking into new png_check_IHDR() in png.c + and report all errors found in the IHDR data. + Eliminated useless call to png_check_cHRM() from pngset.c + +Version 1.4.0beta83 [September 25, 2009] + Revised png_check_IHDR() to eliminate bogus complaint about filter_type. + +Version 1.4.0beta84 [September 30, 2009] + Fixed some inconsistent indentation in pngconf.h + Revised png_check_IHDR() to add a test for width variable less than 32-bit. + +Version 1.4.0beta85 [October 1, 2009] + Revised png_check_IHDR() again, to check info_ptr members instead of + the contents of the returned parameters. + +Version 1.4.0beta86 [October 9, 2009] + Updated the "xcode" project (Alam Arias). + Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). + +Version 1.4.0rc01 [October 19, 2009] + Trivial cosmetic changes. + +Version 1.4.0beta87 [October 30, 2009] + Moved version 1.4.0 back into beta. + +Version 1.4.0beta88 [October 30, 2009] + Revised libpng*.txt section about differences between 1.2.x and 1.4.0 + because most of the new features have now been ported back to 1.2.41 + +Version 1.4.0beta89 [November 1, 2009] + More bugfixes and improvements to CMakeLists.txt (Philip Lowman) + Removed a harmless extra png_set_invert_alpha() from pngwrite.c + Apply png_user_chunk_cache_max within png_decompress_chunk(). + Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate. + +Version 1.4.0beta90 [November 2, 2009] + Removed all remaining WIN32_WCE #ifdefs except those involving the + time.h "tm" structure + +Version 1.4.0beta91 [November 3, 2009] + Updated scripts/pngw32.def and projects/wince/png32ce.def + Copied projects/wince/png32ce.def to the scripts directory. + Added scripts/makefile.wce + Patched ltmain.sh for wince support. + Added PNG_CONVERT_tIME_SUPPORTED macro. + +Version 1.4.0beta92 [November 4, 2009] + Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED + Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED + Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead + of differences from 1.2.41 to 1.4.0) + +Version 1.4.0beta93 [November 7, 2009] + Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and + PNG_ALLOCATED macros to detect deprecated direct access to the + png_struct or info_struct members and other deprecated usage in + applications (John Bowler). + Updated scripts/makefile* to add "-DPNG_CONFIGURE_LIBPNG" to CFLAGS, + to prevent warnings about direct access to png structs by libpng + functions while building libpng. They need to be tested, especially + those using compilers other than gcc. + Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG". + They should work but still need to be updated to remove + references to pnggccrd.c or pngvcrd.c and ASM building. + Added README.txt to the beos, cbuilder5, netware, and xcode projects warning + that they need to be updated, to remove references to pnggccrd.c and + pngvcrd.c and to depend on pngpriv.h + Removed three direct references to read_info_ptr members in pngtest.c + that were detected by the new PNG_DEPSTRUCT macro. + Moved the png_debug macro definitions and the png_read_destroy(), + png_write_destroy() and png_far_to_near() prototypes from png.h + to pngpriv.h (John Bowler) + Moved the synopsis lines for png_read_destroy(), png_write_destroy() + png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. + +Version 1.4.0beta94 [November 9, 2009] + Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Removed dependency of pngtest.o on pngpriv.h in the makefiles. + Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. + +Version 1.4.0beta95 [November 10, 2009] + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c + Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c + Added dependency on pngpriv.h in contrib/pngminim/*/makefile + +Version 1.4.0beta96 [November 12, 2009] + Renamed scripts/makefile.wce to scripts/makefile.cegcc + Revised Makefile.am to use libpng.sys while building libpng.so + so that only PNG_EXPORT functions are exported. + Removed the deprecated png_check_sig() function/macro. + Removed recently removed function names from scripts/*.def + Revised pngtest.png to put chunks in the same order written by pngtest + (evidently the same change made in libpng-1.0beta54 was lost). + Added PNG_PRIVATE macro definition in pngconf.h for possible future use. + +Version 1.4.0beta97 [November 13, 2009] + Restored pngtest.png to the libpng-1.4.0beta7 version. + Removed projects/beos and netware.txt; no one seems to be supporting them. + Revised Makefile.in + +Version 1.4.0beta98 [November 13, 2009] + Added the "xcode" project to zip distributions, + Fixed a typo in scripts/pngwin.def introduced in beta97. + +Version 1.4.0beta99 [November 14, 2009] + Moved libpng-config.in and libpng.pc-configure.in out of the scripts + directory, to libpng-config.in and libpng-pc.in, respectively, and + modified Makefile.am and configure.ac accordingly. Now "configure" + needs nothing from the "scripts" directory. + Avoid redefining PNG_CONST in pngconf.h + +Version 1.4.0beta100 [November 14, 2009] + Removed ASM builds from projects/visualc6 and projects/visualc71 + Removed scripts/makefile.nommx and makefile.vcawin32 + Revised CMakeLists.txt to account for new location of libpng-config.in + and libpng-pc.in + Updated INSTALL to reflect removal and relocation of files. + +Version 1.4.0beta101 [November 14, 2009] + Restored the binary files (*.jpg, *.png, some project files) that were + accidentally deleted from the zip and 7z distributions when the xcode + project was added. + +Version 1.4.0beta102 [November 18, 2009] + Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. + Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. + Moved descriptions of makefiles and other scripts out of INSTALL into + scripts/README.txt + Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. + +Version 1.4.0beta103 [November 21, 2009] + Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt + Align row_buf on 16-byte boundary in memory. + Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call + to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 + changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone + needs this feature. + Make the 'png_jmpbuf' macro expand to a call that records the correct + longjmp function as well as returning a pointer to the setjmp + jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. + (John Bowler) + +Version 1.4.0beta104 [November 22, 2009] + Removed png_longjmp_ptr from scripts/*.def and libpng.3 + Rebuilt configure scripts with autoconf-2.65 + +Version 1.4.0beta105 [November 25, 2009] + Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() + to accomplish alpha premultiplication when + PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. + Changed "/255" to "/255.0" in background calculations to make it clear + that the 255 is used as a double. + +Version 1.4.0beta106 [November 27, 2009] + Removed premultiplied alpha feature. + +Version 1.4.0beta107 [December 4, 2009] + Updated README + Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. + Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. + Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco + to put png.h and pngconf.h in $prefix/include, like the other scripts, + instead of in $prefix/include/libpng. Also revised makefile.sco + to put them in $prefix/include/libpng15 instead of in + $prefix/include/libpng/libpng15. + +Version 1.4.0beta108 [December 11, 2009] + Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile + Relocated png_do_chop() to its original position in pngrtran.c; the + change in version 1.2.41beta08 caused transparency to be handled wrong + in some 16-bit datastreams (Yusaku Sugai). + +Version 1.4.0beta109 [December 13, 2009] + Added "bit_depth" parameter to the private png_build_gamma_table() function. + Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the + PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit + tables. + +Version 1.4.0rc02 [December 20, 2009] + Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c + +Version 1.4.0rc03 [December 22, 2009] + Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt + (revising the change in 1.4.0beta99) + +Version 1.4.0rc04 [December 25, 2009] + Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in pngset.c to be consistent with other changes in version 1.2.38. + +Version 1.4.0rc05 [December 25, 2009] + Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and + Makefile.in to be consistent with changes in libpng-1.4.0rc03 + +Version 1.4.0rc06 [December 29, 2009] + Reverted the gamma_table changes from libpng-1.4.0beta109. + Fixed some indentation errors. + +Version 1.4.0rc07 [January 1, 2010] + Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. + Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c + Update copyright year to 2010. + +Version 1.4.0rc08 [January 2, 2010] + Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr + in pngtest.c + +Version 1.4.0 [January 3, 2010] + No changes. + +Version 1.4.1beta01 [January 8, 2010] + Updated CMakeLists.txt for consistent indentation and to avoid an + unclosed if-statement warning (Philip Lowman). + Revised Makefile.am and Makefile.in to remove references to Y2KINFO, + KNOWNBUG, and libpng.la (Robert Schwebel). + Revised the makefiles to install the same files and symbolic + links as configure, except for libpng.la and libpng14.la. + Make png_set|get_compression_buffer_size() available even when + PNG_WRITE_SUPPORTED is not enabled. + Revised Makefile.am and Makefile.in to simplify their maintenance. + Revised scripts/makefile.linux to install a link to libpng14.so.14.1 + +Version 1.4.1beta02 [January 9, 2010] + Revised the rest of the makefiles to install a link to libpng14.so.14.1 + +Version 1.4.1beta03 [January 10, 2010] + Removed png_set_premultiply_alpha() from scripts/*.def + +Version 1.4.1rc01 [January 16, 2010] + No changes. + +Version 1.4.1beta04 [January 23, 2010] + Revised png_decompress_chunk() to improve speed and memory usage when + decoding large chunks. + Added png_set|get_chunk_malloc_max() functions. + +Version 1.4.1beta05 [January 26, 2010] + Relocated "int k" declaration in pngtest.c to minimize its scope. + +Version 1.4.1beta06 [January 28, 2010] + Revised png_decompress_chunk() to use a two-pass method suggested by + John Bowler. + +Version 1.4.1beta07 [February 6, 2010] + Folded some long lines in the source files. + Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + and a PNG_USER_LIMITS_SUPPORTED flag. + Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as + png_ptr->png_user_chunk_malloc_max. + Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. + +Version 1.4.1beta08 [February 6, 2010] + Minor cleanup and updating of dates and copyright year. + +Version 1.5.0beta01 [February 7, 2010] + Moved declaration of png_struct into private pngstruct.h and png_info + into pnginfo.h + +Version 1.4.1beta09 and 1.5.0beta02 [February 7, 2010] + Reverted to original png_push_save_buffer() code. + +Version 1.4.1beta10 and 1.5.0beta03 [February 8, 2010] + Return allocated "old_buffer" in png_push_save_buffer() before + calling png_error(), to avoid a potential memory leak. + Updated configure script to use SO number 15. + +Version 1.5.0beta04 [February 9, 2010] + Removed malformed "incomplete struct declaration" of png_info from png.h + +Version 1.5.0beta05 [February 12, 2010] + Removed PNG_DEPSTRUCT markup in pngstruct.h and pnginfo.h, and undid the + linewrapping that it entailed. + Revised comments in pngstruct.h and pnginfo.h and added pointers to + the libpng license. + Changed PNG_INTERNAL to PNG_EXPOSE_INTERNAL_STRUCTURES + Removed the cbuilder5 project, which has not been updated to 1.4.0. + +Version 1.4.1beta12 and 1.5.0beta06 [February 14, 2010] + Fixed type declaration of png_get_chunk_malloc_max() in pngget.c (Daisuke + Nishikawa) + +Version 1.5.0beta07 [omitted] + +Version 1.5.0beta08 [February 19, 2010] + Changed #ifdef PNG_NO_STDIO_SUPPORTED to #ifdef PNG_NO_CONSOLE_IO_SUPPORTED + wherever png_snprintf() is used to construct error and warning messages. + Noted in scripts/makefile.mingw that it expects to be run under MSYS. + Removed obsolete unused MMX-querying support from contrib/gregbook + Added exported png_longjmp() function. + Removed the AIX redefinition of jmpbuf in png.h + Added -D_ALLSOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when building on AIX. + +Version 1.5.0beta09 [February 19, 2010] + Removed -D_ALLSOURCE from configure.ac, makefile.aix, and CMakeLists.txt. + Changed the name of png_ptr->jmpbuf to png_ptr->png_jmpbuf in pngstruct.h + +Version 1.5.0beta10 [February 25, 2010] + Removed unused gzio.c from contrib/pngminim gather and makefile scripts + Removed replacement error handlers from contrib/gregbook. Because of + the new png_longjmp() function they are no longer needed. + +Version 1.5.0beta11 [March 6, 2010] + Removed checking for already-included setjmp.h from pngconf.h + Fixed inconsistent indentations and made numerous cosmetic changes. + Revised the "SEE ALSO" style of libpng.3, libpngpf.3, and png.5 + +Version 1.5.0beta12 [March 9, 2010] + Moved "#include png.h" inside pngpriv.h and removed "#include png.h" from + the source files, along with "#define PNG_EXPOSE_INTERNAL_STRUCTURES" + and "#define PNG_NO_PEDANTIC_WARNINGS" (John Bowler). + Created new pngdebug.h and moved debug definitions there. + +Version 1.5.0beta13 [March 10, 2010] + Protect pngstruct.h, pnginfo.h, and pngdebug.h from being included twice. + Revise the "#ifdef" blocks in png_inflate() so it will compile when neither + PNG_USER_CHUNK_MALLOC_MAX nor PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + is defined. + Removed unused png_measure_compressed_chunk() from pngpriv.h and libpngpf.3 + Moved the 'config.h' support from pngconf.h to pngpriv.h + Removed PNGAPI from the png_longjmp_ptr typedef. + Eliminated dependence of pngtest.c on the private pngdebug.h file. + Make all png_debug macros into *unterminated* statements or + expressions (i.e. a trailing ';' must always be added) and correct + the format statements in various png_debug messages. + +Version 1.5.0beta14 [March 14, 2010] + Removed direct access to png_ptr->io_ptr from the Windows code in pngtest.c + Revised Makefile.am to account for recent additions and replacements. + Corrected CE and OS/2 DEF files (scripts/png*def) for symbols removed and + added ordinal numbers to the Windows DEF file and corrected the duplicated + ordinal numbers on CE symbols that are commented out. + Added back in export symbols that can be present in the Windows build but + are disabled by default. + PNG_EXPORT changed to include an 'ordinal' field for DEF file generation. + PNG_CALLBACK added to make callback definitions uniform. PNGAPI split + into PNGCAPI (base C form), PNGAPI (exports) and PNGCBAPI (callbacks), + and appropriate changes made to all files. Cygwin builds re-hinged to + allow procedure call standard changes and to remove the need for the DEF + file (fixes build on Cygwin). + Enabled 'attribute' warnings that are relevant to library APIs and callbacks. + Changed rules for generation of the various symbol files and added a new + rule for a DEF file (which is also added to the distribution). + Updated the symbol file generation to stop it adding spurious spaces + to EOL (coming from preprocessor macro expansion). Added a facility + to join tokens in the output and rewrite *.dfn to use this. + Eliminated scripts/*.def in favor of libpng.def; updated projects/visualc71 + and removed scripts/makefile.cygwin. + Made PNG_BUILD_DLL safe: it can be set whenever a DLL is being built. + Removed the include of sys/types.h - apparently unnecessary now on the + platforms on which it happened (all but Mac OS and RISC OS). + Moved the Mac OS test into pngpriv.h (the only place it is used.) + +Version 1.5.0beta15 [March 17, 2010] + Added symbols.chk target to Makefile.am to validate the symbols in png.h + against the new DEF file scripts/symbols.def. + Changed the default DEF file back to pngwin.def. + Removed makefile.mingw. + Eliminated PNG_NO_EXTERN and PNG_ALL_EXTERN + +Version 1.5.0beta16 [April 1, 2010] + Make png_text_struct independent of PNG_iTXt_SUPPORTED, so that + fields are initialized in all configurations. The READ/WRITE + macros (PNG_(READ|WRITE)_iTXt_SUPPORTED) still function as + before to disable code to actually read or write iTXt chunks + and iTXt_SUPPORTED can be used to detect presence of either + read or write support (but it is probably better to check for + the one actually required - read or write.) + Combined multiple png_warning() calls for a single error. + Restored the macro definition of png_check_sig(). + +Version 1.5.0beta17 [April 17, 2010] + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Documented the fact that png_set_dither() was disabled since libpng-1.4.0. + Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect + more accurately what it actually does. At the same time, renamed + the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to + PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Freeze build-time only configuration in the build. + In all prior versions of libpng most configuration options + controlled by compiler #defines had to be repeated by the + application code that used libpng. This patch changes this + so that compilation options that can only be changed at build + time are frozen in the build. Options that are compiler + dependent (and those that are system dependent) are evaluated + each time - pngconf.h holds these. Options that can be changed + per-file in the application are in png.h. Frozen options are + in the new installed header file pnglibconf.h (John Bowler) + Removed the xcode project because it has not been updated to work + with libpng-1.5.0. + Removed the ability to include optional pngusr.h + +Version 1.5.0beta18 [April 17, 2010] + Restored the ability to include optional pngusr.h + Moved replacements for png_error() and png_warning() from the + contrib/pngminim project to pngerror.c, for use when warnings or + errors are disabled via PNG_NO_WARN or PNG_NO_ERROR_TEXT, to avoid + storing unneeded error/warning text. + Updated contrib/pngminim project to work with the new pnglibconf.h + Added some PNG_NO_* defines to contrib/pngminim/*/pngusr.h to save space. + +Version 1.5.0beta19 [April 24, 2010] + Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the functions + to read and write ints to be disabled independently of PNG_USE_READ_MACROS, + which allows libpng to be built with the functions even though the default + is to use the macros - this allows applications to choose at app build + time whether or not to use macros (previously impossible because the + functions weren't in the default build.) + Changed Windows calling convention back to __cdecl for API functions. + For Windows/x86 platforms only: + __stdcall is no longer needed for Visual Basic, so libpng-1.5.0 uses + __cdecl throughout (both API functions and callbacks) on Windows/x86 + platforms. + Replaced visualc6 and visualc71 projects with new vstudio project + Relaxed the overly-restrictive permissions of some files. + +Version 1.5.0beta20 [April 24, 2010] + Relaxed more overly-restrictive permissions of some files. + +Version 1.5.0beta21 [April 27, 2010] + Removed some unwanted binary bytes and changed CRLF to NEWLINE in the new + vstudio project files, and some trivial editing of some files in the + scripts directory. + Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in + contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. + +Version 1.5.0beta22 [April 28, 2010] + Fixed dependencies of GET_INT_32 - it does not require READ_INT_FUNCTIONS + because it has a macro equivalent. + Improved the options.awk script; added an "everything off" option. + Revised contrib/pngminim to use the "everything off" option in pngusr.dfa. + +Version 1.5.0beta23 [April 29, 2010] + Corrected PNG_REMOVED macro to take five arguments. + The macro was documented with two arguments (name,ordinal), however + the symbol checking .dfn files assumed five arguments. The five + argument form seems more useful so it is changed to that. + Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in gregbook/readpng2.c + Corrected protection of png_get_user_transform_ptr. The API declaration in + png.h is removed if both READ and WRITE USER_TRANSFORM are turned off + but was left defined in pngtrans.c + Added logunsupported=1 to cause pnglibconf.h to document disabled options. + This makes the installed pnglibconf.h more readable but causes no + other change. The intention is that users of libpng will find it + easier to understand if an API they need is missing. + Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. + Removed dummy_inflate.c from contrib/pngminim/encoder + Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. + +Version 1.5.0beta24 [May 7, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + +Version 1.5.0beta25 [June 18, 2010] + In pngpread.c: png_push_have_row() add check for new_row > height + Removed the now-redundant check for out-of-bounds new_row from example.c + +Version 1.5.0beta26 [June 18, 2010] + In pngpread.c: png_push_process_row() add check for too many rows. + +Version 1.5.0beta27 [June 18, 2010] + Removed the check added in beta25 as it is now redundant. + +Version 1.5.0beta28 [June 20, 2010] + Rewrote png_process_IDAT_data to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the new (beta26) check in png_push_process_row(). + +Version 1.5.0beta29 [June 21, 2010] + Revised scripts/options.awk to work on Sunos (but still doesn't work) + Added comment to options.awk and contrib/pngminim/*/makefile to try nawk. + +Version 1.5.0beta30 [June 22, 2010] + Stop memory leak when reading a malformed sCAL chunk. + +Version 1.5.0beta31 [June 26, 2010] + Revised pngpread.c patch of beta28 to avoid an endless loop. + Removed some trailing blanks. + +Version 1.5.0beta32 [June 26, 2010] + Removed leftover scripts/options.patch and scripts/options.rej + +Version 1.5.0beta33 [July 6, 3010] + Made FIXED and FLOATING options consistent in the APIs they enable and + disable. Corrected scripts/options.awk to handle both command line + options and options specified in the .dfa files. + Changed char *msg to PNG_CONST char *msg in pngrutil.c + Make png_set_sRGB_gAMA_and_cHRM set values using either the fixed or + floating point APIs, but not both. + Reversed patch to remove error handler when the jmp_buf is stored in the + main program structure, not the png_struct. + The error handler is needed because the default handler in libpng will + always use the jmp_buf in the library control structure; this is never + set. The gregbook code is a useful example because, even though it + uses setjmp/longjmp, it shows how error handling can be implemented + using control mechanisms not directly supported by libpng. The + technique will work correctly with mechanisms such as Microsoft + Structure Exceptions or C++ exceptions (compiler willing - note that gcc + does not by default support interworking of C and C++ error handling.) + Reverted changes to call png_longjmp in contrib/gregbook where it is not + appropriate. If mainprog->jmpbuf is used by setjmp, then png_longjmp + cannot be used. + Changed "extern PNG_EXPORT" to "PNG_EXPORT" in png.h (Jan Nijtmans) + Changed "extern" to "PNG_EXTERN" in pngpriv.h (except for the 'extern "C" {') + +Version 1.5.0beta34 [July 12, 2010] + Put #ifndef PNG_EXTERN, #endif around the define PNG_EXTERN in pngpriv.h + +Version 1.5.0beta35 [July 24, 2010] + Removed some newly-added TAB characters. + Added -DNO_PNG_SNPRINTF to CFLAGS in scripts/makefile.dj2 + Moved the definition of png_snprintf() outside of the enclosing + #ifdef blocks in pngconf.h + +Version 1.5.0beta36 [July 29, 2010] + Patches by John Bowler: + Fixed point APIs are now supported throughout (no missing APIs). + Internal fixed point arithmetic support exists for all internal floating + point operations. + sCAL validates the floating point strings it is passed. + Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2 + Two new APIs exist to get the number of passes without turning on the + 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. + 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 + works in the FP case too.) + Most floating point APIs now simply call the fixed point APIs after + converting the values to the fixed point form used in the PNG file. + The standard headers no longer include zlib.h, which is currently only + required for pngstruct.h and can therefore be internal. + Revised png_get_int_32 to undo the PNG two's complement representation of + negative numbers. + +Version 1.5.0beta37 [July 30, 2010] + Added a typecast in png_get_int_32() in png.h and pngrutil.h to avoid + a compiler warning. + Replaced oFFs 0,0 with oFFs -10,20 in pngtest.png + +Version 1.5.0beta38 [July 31, 2010] + Implemented remaining "_fixed" functions. + Corrected a number of recently introduced warnings mostly resulting from + safe but uncast assignments to shorter integers. Also added a zlib + VStudio release library project because the latest zlib Official Windows + build does not include such a thing. + Revised png_get_int_16() to be similar to png_get_int_32(). + Restored projects/visualc71. + +Version 1.5.0beta39 [August 2, 2010] + VisualC/GCC warning fixes, VisualC build fixes + The changes include support for function attributes in VC in addition to + those already present in GCC - necessary because without these some + warnings are unavoidable. Fixes include signed/unsigned fixes in + pngvalid and checks with gcc -Wall -Wextra -Wunused. + VC requires function attributes on function definitions as well as + declarations, PNG_FUNCTION has been added to enable this and the + relevant function definitions changed. + +Version 1.5.0beta40 [August 6, 2010] + Correct use of _WINDOWS_ in pngconf.h + Removed png_mem_ #defines; they are no longer used. + Added the sRGB chunk to pngtest.png + +Version 1.5.0beta41 [August 11, 2010] + Added the cHRM chunk to pngtest.png + Don't try to use version-script with cygwin/mingw. + Revised contrib/gregbook to work under cygwin/mingw. + +Version 1.5.0beta42 [August 18, 2010] + Add .dll.a to the list of extensions to be symlinked by Makefile.am (Yaakov) + Made all API functions that have const arguments and constant string + literal pointers declare them (John Bowler). + +Version 1.5.0beta43 [August 20, 2010] + Removed spurious tabs, shorten long lines (no source change) + Also added scripts/chkfmt to validate the format of all the files that can + reasonably be validated (it is suggested to run "make distclean" before + checking, because some machine generated files have long lines.) + Reformatted the CHANGES file to be more consistent throughout. + Made changes to address various issues identified by GCC, mostly + signed/unsigned and shortening problems on assignment but also a few + difficult to optimize (for GCC) loops. + Fixed non-GCC fixed point builds. In png.c a declaration was misplaced + in an earlier update. Fixed to declare the auto variables at the head. + Use cexcept.h in pngvalid.c. + +Version 1.5.0beta44 [August 24, 2010] + Updated CMakeLists.txt to use CMAKE_INSTALL_LIBDIR variable; useful for + installing libpng in /usr/lib64 (Funda Wang). + Revised CMakeLists.txt to put the man pages in share/man/man* not man/man* + Revised CMakeLists.txt to make symlinks instead of copies when installing. + Changed PNG_LIB_NAME from pngNN to libpngNN in CMakeLists.txt (Philip Lowman) + Implemented memory checks within pngvalid + Reformatted/rearranged pngvalid.c to assist use of progressive reader. + Check interlaced images in pngvalid + Clarified pngusr.h comments in pnglibconf.dfa + Simplified the pngvalid error-handling code now that cexcept.h is in place. + Implemented progressive reader in pngvalid.c for standard tests + Implemented progressive read in pngvalid.c gamma tests + Turn on progressive reader in pngvalid.c by default and tidy code. + +Version 1.5.0beta45 [August 26, 2010] + Added an explicit make step to projects/vstudio for pnglibconf.h + Also corrected zlib.vcxproj into which Visual Studio had introduced + what it calls an "authoring error". The change to make pnglibconf.h + simply copies the file; in the future it may actually generate the + file from scripts/pnglibconf.dfa as the other build systems do. + Changed pngvalid to work when floating point APIs are disabled + Renamed the prebuilt scripts/pnglibconf.h to scripts/pnglibconf.h.prebuilt + Supply default values for PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX + in pngpriv.h in case the user neglected to define them in their pngusr.h + +Version 1.5.0beta46 [August 28, 2010] + Added new private header files to libpng_sources in CMakeLists.txt + Added PNG_READ_16BIT, PNG_WRITE_16BIT, and PNG_16BIT options. + Added reference to scripts/pnglibconf.h.prebuilt in the visualc71 project. + +Version 1.5.0beta47 [September 11, 2010] + Fixed a number of problems with 64-bit compilation reported by Visual + Studio 2010 (John Bowler). + +Version 1.5.0beta48 [October 4, 2010] + Updated CMakeLists.txt (Philip Lowman). + Revised autogen.sh to recognize and use $AUTOCONF, $AUTOMAKE, $AUTOHEADER, + $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + Fixed problem with symbols creation in Makefile.am which was assuming that + all versions of ccp write to standard output by default (Martin Banky). The + bug was introduced in libpng-1.2.9beta5. + Removed unused mkinstalldirs. + +Version 1.5.0beta49 [October 8, 2010] + Undid Makefile.am revision of 1.5.0beta48. + +Version 1.5.0beta50 [October 14, 2010] + Revised Makefile.in to account for mkinstalldirs being removed. + Added some "(unsigned long)" typecasts in printf statements in pngvalid.c. + Suppressed a compiler warning in png_handle_sPLT(). + Check for out-of-range text compression mode in png_set_text(). + +Version 1.5.0beta51 [October 15, 2010] + Changed embedded dates to "(PENDING RELEASE) in beta releases (and future + rc releases) to minimize the difference between releases. + +Version 1.5.0beta52 [October 16, 2010] + Restored some of the embedded dates (in png.h, png.c, documentation, etc.) + +Version 1.5.0beta53 [October 18, 2010] + Updated INSTALL to mention using "make maintainer-clean" and to remove + obsolete statement about a custom ltmain.sh + Disabled "color-tests" by default in Makefile.am so it will work with + automake versions earlier than 1.11.1 + Use document name "libpng-manual.txt" instead of "libpng-.txt" + to simplify version differences. + Removed obsolete remarks about setjmp handling from INSTALL. + Revised and renamed the typedef in png.h and png.c that was designed + to catch library and header mismatch. + +Version 1.5.0beta54 [November 10, 2010] + Require 48 bytes, not 64 bytes, for big_row_buf in overflow checks. + Used a consistent structure for the pngget.c functions. + +Version 1.5.0beta55 [November 21, 2010] + Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) + Moved reading of file signature into png_read_sig (Cosmin) + Fixed atomicity of chunk header serialization (Cosmin) + Added test for io_state in pngtest.c (Cosmin) + Added "#!/bin/sh" at the top of contrib/pngminim/*/gather.sh scripts. + Changes to remove gcc warnings (John Bowler) + Certain optional gcc warning flags resulted in warnings in libpng code. + With these changes only -Wconversion and -Wcast-qual cannot be turned on. + Changes are trivial rearrangements of code. -Wconversion is not possible + for pngrutil.c (because of the widespread use of += et al on variables + smaller than (int) or (unsigned int)) and -Wcast-qual is not possible + with pngwio.c and pngwutil.c because the 'write' callback and zlib + compression both fail to declare their input buffers with 'const'. + +Version 1.5.0beta56 [December 7, 2010] + Added the private PNG_UNUSED() macro definition in pngpriv.h. + Added some commentary about PNG_EXPORT in png.h and pngconf.h + Revised PNG_EXPORT() macro and added PNG_EXPORTA() macro, with the + objective of simplifying and improving the cosmetic appearance of png.h. + Fixed some incorrect "=" macro names in pnglibconf.dfa + Included documentation of changes in 1.5.0 from 1.4.x in libpng-manual.txt + +Version 1.5.0beta57 [December 9, 2010] + Documented the pngvalid gamma error summary with additional comments and + print statements. + Improved missing symbol handling in checksym.awk; symbols missing in both + the old and new files can now be optionally ignored, treated as errors + or warnings. + Removed references to pngvcrd.c and pnggccrd.c from the vstudio project. + Updated "libpng14" to "libpng15" in the visualc71 project. + Enabled the strip16 tests in pngvalid.` + Don't display test results (except PASS/FAIL) when running "make test". + Instead put them in pngtest-log.txt + Added "--with-zprefix=" to configure.ac + Updated the prebuilt configuration files to autoconf version 2.68 + +Version 1.5.0beta58 [December 19, 2010] + Fixed interlace image handling and add test cases (John Bowler) + Fixed the clean rule in Makefile.am to remove pngtest-log.txt + Made minor changes to work around warnings in gcc 3.4 + +Version 1.5.0rc01 [December 27, 2010] + No changes. + +Version 1.5.0rc02 [December 27, 2010] + Eliminated references to the scripts/*.def files in project/visualc71. + +Version 1.5.0rc03 [December 28, 2010] + Eliminated scripts/*.def and revised Makefile.am accordingly + +Version 1.5.0rc04 [December 29, 2010] + Fixed bug in background transformation handling in pngrtran.c (it was + looking for the flag in png_ptr->transformations instead of in + png_ptr->flags) (David Raymond). + +Version 1.5.0rc05 [December 31, 2010] + Fixed typo in a comment in CMakeLists.txt (libpng14 => libpng15) (Cosmin) + +Version 1.5.0rc06 [January 4, 2011] + Changed the new configure option "zprefix=string" to "zlib-prefix=string" + +Version 1.5.0rc07 [January 4, 2011] + Updated copyright year. + +Version 1.5.0 [January 6, 2011] + No changes. + +version 1.5.1beta01 [January 8, 2011] + 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(). This change happened + in version 1.5.0beta36 but is not noted in the CHANGES. 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 a failure to handle palette mapped images correctly. + +Version 1.5.1beta02 [January 14, 2011] + Fixed a bug in handling of interlaced images (bero at arklinux.org). + Updated CMakeLists.txt (Clifford Yapp) + +Version 1.5.1beta03 [January 14, 2011] + Fixed typecasting of some png_debug() statements (Cosmin) + +Version 1.5.1beta04 [January 16, 2011] + 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. + Prefixed variable names index, div, exp, gamma with "png_" to avoid "shadow" + warnings, and (mistakenly) changed png_exp() to exp(). + +Version 1.5.1beta05 [January 16, 2011] + Changed variable names png_index, png_div, png_exp, and png_gamma to + char_index, divisor, exp_b10, and gamma_val, respectively, and + changed exp() back to png_exp(). + +Version 1.5.1beta06 [January 20, 2011] + 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. + +Version 1.5.1beta07 [January 22, 2011] + 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. + +Version 1.5.1beta08 [January 23, 2011] + 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.) + +Version 1.5.1beta09 [January 24, 2011] + 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. + +Version 1.5.1beta10 [January 27, 2010] + 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. + +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 + architectures. + Added transform tests to pngvalid and simplified the arguments. + +Version 1.5.1rc01 [January 29, 2011] + No changes. + +Version 1.5.1rc02 [January 31, 2011] + Added a request in the manual that applications do not use "png_" or + "PNG_" to begin any of their own symbols. + Changed PNG_UNUSED to "(void)param;" and updated the commentary in pngpriv.h + +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] + +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 diff --git a/extern/libpng/include/CMakeLists.txt b/extern/libpng/include/CMakeLists.txt new file mode 100644 index 0000000000..8f2b7e8b45 --- /dev/null +++ b/extern/libpng/include/CMakeLists.txt @@ -0,0 +1,406 @@ +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +if(UNIX AND NOT DEFINED CMAKE_BUILD_TYPE) + if(CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION EQUAL 4) + # workaround CMake 2.4.x bug + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING + "Choose the type of build, options are: + None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) + Debug + Release + RelWithDebInfo + MinSizeRel.") + else() + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING + "Choose the type of build, options are: + None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) + Debug + Release + RelWithDebInfo + MinSizeRel.") + endif() +endif() + +project(libpng C) +enable_testing() + +# Copyright (C) 2007-2011 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +set(PNGLIB_MAJOR 1) +set(PNGLIB_MINOR 5) +set(PNGLIB_RELEASE 2) +set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) +set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) + +# needed packages +find_package(ZLIB REQUIRED) +include_directories(${ZLIB_INCLUDE_DIR}) + +if(NOT WIN32) + find_library(M_LIBRARY + NAMES m + PATHS /usr/lib /usr/local/lib + ) + if(NOT M_LIBRARY) + message(STATUS + "math library 'libm' not found - floating point support disabled") + endif() +else() + # not needed on windows + set(M_LIBRARY "") +endif() + +# COMMAND LINE OPTIONS +if(DEFINED PNG_SHARED) + option(PNG_SHARED "Build shared lib" ${PNG_SHARED}) +else() + option(PNG_SHARED "Build shared lib" ON) +endif() +if(DEFINED PNG_STATIC) + option(PNG_STATIC "Build static lib" ${PNG_STATIC}) +else() + option(PNG_STATIC "Build static lib" ON) +endif() + +if(MINGW) + option(PNG_TESTS "Build pngtest" NO) +else() + option(PNG_TESTS "Build pngtest" YES) +endif() + +option(PNG_NO_CONSOLE_IO "FIXME" YES) +option(PNG_NO_STDIO "FIXME" YES) +option(PNG_DEBUG "Build with debug output" NO) +option(PNGARG "FIXME" YES) +#TODO: +# PNG_CONSOLE_IO_SUPPORTED + +# maybe needs improving, but currently I don't know when we can enable what :) +set(png_asm_tmp "OFF") +if(NOT WIN32) + find_program(uname_executable NAMES uname PATHS /bin /usr/bin /usr/local/bin) + if(uname_executable) + exec_program(${uname_executable} + ARGS --machine OUTPUT_VARIABLE uname_output) + if("uname_output" MATCHES "^.*i[1-9]86.*$") + set(png_asm_tmp "ON") + else("uname_output" MATCHES "^.*i[1-9]86.*$") + set(png_asm_tmp "OFF") + endif("uname_output" MATCHES "^.*i[1-9]86.*$") + endif(uname_executable) +else() + # this env var is normally only set on win64 + set(TEXT "ProgramFiles(x86)") + if("$ENV{${TEXT}}" STREQUAL "") + set(png_asm_tmp "ON") + endif("$ENV{${TEXT}}" STREQUAL "") +endif() + +# SET LIBNAME +set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) + +# to distinguish between debug and release lib +set(CMAKE_DEBUG_POSTFIX "d") + +# Use the prebuilt pnglibconf.h file from the scripts folder +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# OUR SOURCES +set(libpng_public_hdrs + png.h + pngconf.h + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h +) +set(libpng_sources + ${libpng_public_hdrs} + pngdebug.h + pnginfo.h + pngpriv.h + pngstruct.h + png.c + pngerror.c + pngget.c + pngmem.c + pngpread.c + pngread.c + pngrio.c + pngrtran.c + pngrutil.c + pngset.c + pngtrans.c + pngwio.c + pngwrite.c + pngwtran.c + pngwutil.c +) +set(pngtest_sources + pngtest.c +) +# SOME NEEDED DEFINITIONS + +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) + +if(PNG_SHARED OR NOT MSVC) + #if building msvc static this has NOT to be defined + add_definitions(-DZLIB_DLL) +endif() + + +if(PNG_CONSOLE_IO_SUPPORTED) + add_definitions(-DPNG_CONSOLE_IO_SUPPORTED) +endif() + +if(PNG_NO_CONSOLE_IO) + add_definitions(-DPNG_NO_CONSOLE_IO) +endif() + +if(PNG_NO_STDIO) + add_definitions(-DPNG_NO_STDIO) +endif() + +if(PNG_DEBUG) + add_definitions(-DPNG_DEBUG) +endif() + +if(NOT M_LIBRARY AND NOT WIN32) + add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED) +endif() + +# NOW BUILD OUR TARGET +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR}) + +if(PNG_SHARED) + add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") + set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") + endif() + target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY}) +endif() + +if(PNG_STATIC) +# does not work without changing name + set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static) + add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources}) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") + endif() + target_link_libraries(${PNG_LIB_NAME_STATIC} ${ZLIB_LIBRARY} ${M_LIBRARY}) +endif() + + +if(PNG_SHARED AND WIN32) + set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) +endif() + +if(PNG_TESTS AND PNG_SHARED) + # does not work with msvc due to png_lib_ver issue + add_executable(pngtest ${pngtest_sources}) + target_link_libraries(pngtest ${PNG_LIB_NAME}) + add_test(pngtest ./pngtest ${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png) +endif() + +# +# Set a variable with CMake code which: +# Creates a symlink from src to dest (if possible) or alternatively +# copies if different. +macro(_png_generate_symlink_code CODE SRC DEST) + if(WIN32 AND NOT CYGWIN) + set(_png_gsc_message "Copying ${SRC} to ${DEST} if needed") + set(_png_gsc_operation "copy_if_different") + else() + set(_png_gsc_message "Symlinking ${SRC} to ${DEST}") + set(_png_gsc_operation "create_symlink") + endif() + + set(${CODE} " + message(STATUS \"${_png_gsc_message}\") + execute_process(COMMAND \${CMAKE_COMMAND} -E ${_png_gsc_operation} + \"${SRC}\" \"${DEST}\") + ") +endmacro() + +# CREATE PKGCONFIG FILES +# we use the same files like ./configure, so we have to set its vars +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif(NOT DEFINED CMAKE_INSTALL_LIBDIR) +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${CMAKE_INSTALL_PREFIX}) +set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +set(includedir ${CMAKE_INSTALL_PREFIX}/include) +set(LIBS "-lz -lm") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY) +_png_generate_symlink_code(PNG_PC_INSTALL_CODE + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc + ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc) +install(CODE ${PNG_PC_INSTALL_CODE}) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY) +_png_generate_symlink_code(PNG_CONFIG_INSTALL_CODE + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config + ${CMAKE_CURRENT_BINARY_DIR}/libpng-config) +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.2 + VERSION 15.${PNGLIB_RELEASE}.0 + SOVERSION 15 + CLEAN_DIRECT_OUTPUT 1) +endif() +if(PNG_STATIC) + # MSVC doesn't use a different file extension for shared vs. static + # libs. We are able to change OUTPUT_NAME to remove the _static + # for all other platforms. + if(NOT MSVC) + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES + OUTPUT_NAME ${PNG_LIB_NAME} + CLEAN_DIRECT_OUTPUT 1) + endif() +endif() + +# If CMake > 2.4.x, we set a variable used below to export +# targets to an export file. +# TODO: Use VERSION_GREATER after our cmake_minimum_required >= 2.6.2 +if(CMAKE_MAJOR_VERSION GREATER 1 AND CMAKE_MINOR_VERSION GREATER 4) + set(PNG_EXPORT_RULE EXPORT libpng) +elseif(CMAKE_MAJOR_VERSION GREATER 2) # future proof + set(PNG_EXPORT_RULE EXPORT libpng) +endif() + +# INSTALL +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) + if(PNG_SHARED) + install(TARGETS ${PNG_LIB_NAME} + ${PNG_EXPORT_RULE} + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + # Create a symlink for libpng.dll.a => libpng15.dll.a on Cygwin + if(CYGWIN) + _png_generate_symlink_code(PNG_SHARED_IMPLIB_INSTALL_CODE + ${PNGLIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX} + libpng${CMAKE_IMPORT_LIBRARY_SUFFIX}) + install(CODE ${PNG_SHARED_IMPLIB_INSTALL_CODE}) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + if(NOT WIN32) + IF(CMAKE_LIBRARY_OUTPUT_DIRECTORY) + _png_generate_symlink_code(PNG_SHARED_INSTALL_CODE + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${PNGLIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}) + install(CODE ${PNG_SHARED_INSTALL_CODE}) + install(FILES + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + ELSE(CMAKE_LIBRARY_OUTPUT_DIRECTORY) + _png_generate_symlink_code(PNG_SHARED_INSTALL_CODE + ${PNGLIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} + libpng${CMAKE_SHARED_LIBRARY_SUFFIX}) + install(CODE ${PNG_SHARED_INSTALL_CODE}) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + ENDIF(CMAKE_LIBRARY_OUTPUT_DIRECTORY) + endif() + endif() + + if(PNG_STATIC) + install(TARGETS ${PNG_LIB_NAME_STATIC} + ${PNG_EXPORT_RULE} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + if(NOT WIN32 OR CYGWIN) + IF(CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + _png_generate_symlink_code(PNG_STATIC_INSTALL_CODE +${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${PNGLIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}) + install(CODE ${PNG_STATIC_INSTALL_CODE}) + install(FILES + ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + ELSE(CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + _png_generate_symlink_code(PNG_STATIC_INSTALL_CODE + ${PNGLIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX} + libpng${CMAKE_STATIC_LIBRARY_SUFFIX}) + install(CODE ${PNG_STATIC_INSTALL_CODE}) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + ENDIF(CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + endif() + endif() +endif() + +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) + install(FILES ${libpng_public_hdrs} DESTINATION include) + install(FILES ${libpng_public_hdrs} DESTINATION include/${PNGLIB_NAME}) +endif() +if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL ) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config + DESTINATION bin) +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + # Install man pages + if(NOT PNG_MAN_DIR) + set(PNG_MAN_DIR "share/man") + endif() + install(FILES libpng.3 libpngpf.3 DESTINATION ${PNG_MAN_DIR}/man3) + install(FILES png.5 DESTINATION ${PNG_MAN_DIR}/man5) + # Install pkg-config files + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config + DESTINATION bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config + DESTINATION bin) +endif() + +# On versions of CMake that support it, create an export file CMake +# users can include() to import our targets +if(PNG_EXPORT_RULE AND NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL ) + install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake) +endif() + +# what's with libpng-$VER%.txt and all the extra files? + + +# UNINSTALL +# do we need this? + + +# DIST +# do we need this? + +# to create msvc import lib for mingw compiled shared lib +# pexports libpng.dll > libpng.def +# lib /def:libpng.def /machine:x86 + diff --git a/extern/libpng/include/LICENSE b/extern/libpng/include/LICENSE new file mode 100644 index 0000000000..6e4808cc0b --- /dev/null +++ b/extern/libpng/include/LICENSE @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.2, March 31, 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 + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +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 + Glenn Randers-Pehrson + Willem van Schaik + +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, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +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, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +March 31, 2011 diff --git a/extern/libpng/include/Makefile.am b/extern/libpng/include/Makefile.am new file mode 100644 index 0000000000..7b8c494c38 --- /dev/null +++ b/extern/libpng/include/Makefile.am @@ -0,0 +1,211 @@ +# Makefile.am: +# Source file for Makefile.in (and hence Makefile) +# + +PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +# libpng does not follow GNU file name conventions + +# "color-tests" requires automake 1.11.1 or later. Enable it if you like, +# to get red "FAIL" and green "PASS" notations during tests. +# AUTOMAKE_OPTIONS = foreign color-tests +AUTOMAKE_OPTIONS = foreign + +# test programs - run on make check, make distcheck +check_PROGRAMS= pngtest pngvalid +pngtest_SOURCES = pngtest.c +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngvalid_SOURCES = pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +TESTS = test-pngtest.sh test-pngvalid-simple.sh test-pngvalid-full.sh +TESTS_ENVIRONMENT= srcdir=$(srcdir) + +# man pages +dist_man_MANS= libpng.3 libpngpf.3 png.5 + +# generate the -config scripts if required +binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +bin_SCRIPTS= @binconfigs@ + +# rules to build libpng, only build the old library on request +lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS = @LIBPNG_DEFINES@ + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ + -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 + +if HAVE_LD_VERSION_SCRIPT + # Versioned symbols and restricted exports + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers +else + # Only restricted exports when possible + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +endif + +#distribute headers in /usr/include/libpng/* +pkgincludedir= $(includedir)/$(PNGLIB_BASENAME) +pkginclude_HEADERS= png.h pngconf.h +nodist_pkginclude_HEADERS= pnglibconf.h + +# pkg-config stuff, note that libpng.pc is always required in order +# to get the correct library +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc + +#extra source distribution files. +EXTRA_DIST= \ + ANNOUNCE CHANGES INSTALL LICENSE README TODO \ + pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ + ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) \ + CMakeLists.txt example.c libpng-manual.txt + +SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk scripts/pnglibconf.dfn + +CLEANFILES= dfn.c dfn?.out pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.* symbols.new pngtest-log.txt \ + $(SCRIPT_CLEANFILES) + +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ +config.sub configure depcomp install-sh ltmain.sh missing + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ + +SUFFIXES = .chk .dfn .out + +$(PNGLIB_BASENAME).pc: libpng.pc + cp libpng.pc $@ + +$(PNGLIB_BASENAME)-config: libpng-config + cp libpng-config $@ + +scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h +scripts/symbols.out: png.h pngconf.h scripts/pnglibconf.h.prebuilt + +libpng.sym: scripts/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/vers.out + rm -f $@ + cp $? $@ +pnglibconf.h: pnglibconf.out + rm -f $@ + cp $? $@ +scripts/pnglibconf.h.prebuilt: + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf.out' and copy that" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) +pngvalid.o pngtest.o: pnglibconf.h + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this stops the read macros interfering +# with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\ + -DPNGLIB_VERSION='@PNGLIB_VERSION@'\ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\ + -DPNG_NO_USE_READ_MACROS -DPNG_BUILDING_SYMBOL_TABLE + +.dfn.out: + rm -f $@ dfn.c dfn?.out + test -d scripts || mkdir scripts + echo '#include "$<"' >dfn.c + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) @LIBPNG_DEFINES@\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) dfn.c > dfn1.out + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + dfn1.out >dfn2.out + $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + rm -f dfn.c dfn[12].out + mv dfn3.out $@ + +# The .dfn file for pnglibconf.h is machine generated +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + ${srcdir}/scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +# Symbol checks (.def and .out files should match) +scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out +.out.chk: + rm -f $@ symbols.new + $(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\ + $< >&2 + mv symbols.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + logunsupported=2 - ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \ + pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h + +test: check-am + +# Extra checks +check: scripts/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# install the .../include headers as links to the new ones +install-data-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/png.h png.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pngconf.h \ + pngconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pnglibconf.h \ + pnglibconf.h + cd $(DESTDIR)$(pkgconfigdir); rm -f libpng.pc + cd $(DESTDIR)$(pkgconfigdir); $(LN_S) $(PNGLIB_BASENAME).pc libpng.pc + +# do evil things to libpng to cause libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ to be used +install-exec-hook: + cd $(DESTDIR)$(bindir); rm -f libpng-config + cd $(DESTDIR)$(bindir); $(LN_S) $(PNGLIB_BASENAME)-config libpng-config + @set -x;\ + cd $(DESTDIR)$(libdir);\ + for ext in a la so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ sl dylib dll.a; do\ + rm -f libpng.$$ext;\ + if test -f $(PNGLIB_BASENAME).$$ext; then\ + $(LN_S) $(PNGLIB_BASENAME).$$ext libpng.$$ext;\ + fi;\ + done + +uninstall-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + rm -f $(DESTDIR)$(pkgconfigdir)/libpng.pc + rm -f $(DESTDIR)$(bindir)/libpng-config + rm -f $(DESTDIR)$(libdir)/libpng.a + rm -f $(DESTDIR)$(libdir)/libpng.la diff --git a/extern/libpng/include/autogen.sh b/extern/libpng/include/autogen.sh new file mode 100755 index 0000000000..5be104eb1d --- /dev/null +++ b/extern/libpng/include/autogen.sh @@ -0,0 +1,34 @@ +#! /bin/sh +# a quick hack script to generate necessary files from +# auto* tools. +# +# WARNING: if you run this you will change the versions +# of the tools which are used and, maybe, required! + +# You can define your own replacements in your environment. +# $AUTOCONF, $AUTOMAKE, $AUTOHEADER, $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + +touch Makefile.am configure.ac +{ + LT=${LIBTOOLIZE-libtoolize} + echo "running $LT" >&2 + $LT --force --copy --automake +} && { + AL=${ACLOCAL-aclocal} + echo "running $AL" >&2 + $AL +} && { + AH=${AUTOHEADER-autoheader} + echo "running $AH [ignore the warnings]" >&2 + $AH +} && { + AM=${AUTOMAKE-automake} + echo "running $AM" >&2 + $AM --force-missing --foreign -a -c +} && { + AC=${AUTOCONF-autoconf} + echo "running $AC" >&2 + $AC +} && + echo "autogen complete" >&2 || + echo "ERROR: autogen.sh failed, autogen is incomplete" >&2 diff --git a/extern/libpng/include/config.guess b/extern/libpng/include/config.guess new file mode 100644 index 0000000000..dc84c68ef7 --- /dev/null +++ b/extern/libpng/include/config.guess @@ -0,0 +1,1501 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/extern/libpng/include/config.h.in b/extern/libpng/include/config.h.in new file mode 100644 index 0000000000..fb2349568c --- /dev/null +++ b/extern/libpng/include/config.h.in @@ -0,0 +1,86 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `pow' function. */ +#undef HAVE_POW + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/extern/libpng/include/config.sub b/extern/libpng/include/config.sub new file mode 100644 index 0000000000..2a55a50751 --- /dev/null +++ b/extern/libpng/include/config.sub @@ -0,0 +1,1705 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/extern/libpng/include/configure.ac b/extern/libpng/include/configure.ac new file mode 100644 index 0000000000..05540c6cd1 --- /dev/null +++ b/extern/libpng/include/configure.ac @@ -0,0 +1,167 @@ +# configure.ac + +dnl Process this file with autoconf to produce a configure script. +dnl +dnl Minor upgrades (compatible ABI): increment the package version +dnl (third field in two places below) and set the PNGLIB_RELEASE +dnl variable. +dnl +dnl Major upgrades (incompatible ABI): increment the package major +dnl version (second field, or first if desired), set the minor +dnl to 0, set PNGLIB_MAJOR below *and* follow the instructions in +dnl Makefile.am to upgrade the package name. + +dnl This is here to prevent earlier autoconf from being used, it +dnl should not be necessary to regenerate configure if the time +dnl stamps are correct +AC_PREREQ(2.59) + +dnl Version number stuff here: + +AC_INIT([libpng], [1.5.2], [png-mng-implement@lists.sourceforge.net]) +AM_INIT_AUTOMAKE +dnl stop configure from automagically running automake +AM_MAINTAINER_MODE + +PNGLIB_VERSION=1.5.2 +PNGLIB_MAJOR=1 +PNGLIB_MINOR=5 +PNGLIB_RELEASE=2 + +dnl End of version number stuff + +AC_CONFIG_SRCDIR([pngget.c]) +AM_CONFIG_HEADER(config.h) + +# Checks for programs. +AC_LANG([C]) +AC_PROG_CC +AC_PROG_LD +AC_PROG_CPP +AC_CHECK_TOOL(SED, sed, :) +AC_CHECK_TOOL(AWK, awk, :) +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +LT_INIT([win32-dll]) + +# On Solaris 10 and 12 CPP gets set to cc -E, however this still +# does some input parsing. We need strict ANSI-C style tokenization, +# check this: +AC_REQUIRE_CPP +AC_MSG_CHECKING([for a C preprocessor that does not parse its input]) +AC_TRY_CPP([1.5.0 16BIT], + [DFNCPP="$CPP"], + [DFNCPP="" + sav_CPP="$CPP" + for CPP in "${CC-cc} -E" "${CC-cc} -E -traditional-cpp" "/lib/cpp" "cpp"; do + AC_TRY_CPP([1.5.0 16BIT], + [DFNCPP="$CPP"] + [break],,) + done + CPP="$sav_CPP"]) +if test -n "$DFNCPP"; then + AC_MSG_RESULT([$DFNCPP]) + AC_SUBST(DFNCPP) +else + AC_MSG_FAILURE([not found], 1) +fi + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([malloc.h stdlib.h string.h strings.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_STRTOD +AC_CHECK_FUNCS([memset], , AC_ERROR([memset not found in libc])) +AC_CHECK_FUNCS([pow], , AC_CHECK_LIB(m, pow, , AC_ERROR([cannot find pow])) ) +AC_ARG_WITH(zlib-prefix, + AC_HELP_STRING([--with-zlib-prefix], + [prefix that may have been used in installed zlib]), + [ZPREFIX=${withval}], + [ZPREFIX='z_']) +AC_CHECK_LIB(z, zlibVersion, , + AC_CHECK_LIB(z, ${ZPREFIX}zlibVersion, , + AC_ERROR([zlib not installed]))) + + +LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG +LIBPNG_DEFINES=$LIBPNG_DEFINES +AC_SUBST(LIBPNG_DEFINES) + +AC_MSG_CHECKING([if libraries can be versioned]) +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + AC_MSG_RESULT(no) +;; +* ) +GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +if test "$GLD"; then + have_ld_version_script=yes + AC_MSG_RESULT(yes) +else + have_ld_version_script=no + AC_MSG_RESULT(no) + AC_MSG_WARN(*** You have not enabled versioned symbols.) +fi +;; +esac + +AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") + +if test "$have_ld_version_script" = "yes"; then + AC_MSG_CHECKING([for symbol prefix]) + SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ + | ${CPP-${CC-gcc} -E} - 2>&1 \ + | ${EGREP-grep} "^PREFIX=" \ + | ${SED-sed} "s:^PREFIX=::"` + AC_SUBST(SYMBOL_PREFIX) + AC_MSG_RESULT($SYMBOL_PREFIX) +fi + +# Substitutions for .in files +AC_SUBST(PNGLIB_VERSION) +AC_SUBST(PNGLIB_MAJOR) +AC_SUBST(PNGLIB_MINOR) +AC_SUBST(PNGLIB_RELEASE) + +# Additional arguments (and substitutions) +# Allow the pkg-config directory to be set +AC_ARG_WITH(pkgconfigdir, + AC_HELP_STRING([--with-pkgconfigdir], + [Use the specified pkgconfig dir (default is libdir/pkgconfig)]), + [pkgconfigdir=${withval}], + [pkgconfigdir='${libdir}/pkgconfig']) + +AC_SUBST([pkgconfigdir]) +AC_MSG_NOTICE([pkgconfig directory is ${pkgconfigdir}]) + +# Make the *-config binary config scripts optional +AC_ARG_WITH(binconfigs, + AC_HELP_STRING([--with-binconfigs], + [Generate shell libpng-config scripts as well as pkg-config data] + [@<:@default=yes@:>@]), + [if test "${withval}" = no; then + binconfigs= + AC_MSG_NOTICE([libpng-config scripts will not be built]) + else + binconfigs='${binconfigs}' + fi], + [binconfigs='${binconfigs}']) +AC_SUBST([binconfigs]) + +# Config files, substituting as above +AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) +AC_CONFIG_FILES([libpng-config:libpng-config.in], + [chmod +x libpng-config]) + +AC_OUTPUT diff --git a/extern/libpng/include/contrib/gregbook/COPYING b/extern/libpng/include/contrib/gregbook/COPYING new file mode 100644 index 0000000000..a3e9774796 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/extern/libpng/include/contrib/gregbook/LICENSE b/extern/libpng/include/contrib/gregbook/LICENSE new file mode 100644 index 0000000000..d9567178cb --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/LICENSE @@ -0,0 +1,50 @@ + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + --------------------------------------------------------------------------- diff --git a/extern/libpng/include/contrib/gregbook/Makefile.mingw32 b/extern/libpng/include/contrib/gregbook/Makefile.mingw32 new file mode 100644 index 0000000000..e70a59aef2 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/Makefile.mingw32 @@ -0,0 +1,130 @@ +# Sample makefile for rpng-win / rpng2-win / wpng using mingw32-gcc and make. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# The programs built by this makefile are described in the book, +# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and +# Associates, 1999). Go buy a copy, eh? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# Invoke this makefile from a DOS-prompt window via: +# +# make -f Makefile.mingw32 +# +# This makefile assumes libpng and zlib have already been built or downloaded +# and are in subdirectories at the same level as the current subdirectory +# (as indicated by the PNGDIR and ZDIR macros below). It makes no assumptions +# at all about the mingw32 installation tree (W32DIR). Edit as appropriate. +# +# Note that the names of the dynamic and static libpng and zlib libraries +# used below may change in later releases of the libraries. This makefile +# builds both statically and dynamically linked executables by default. +# (You need only one set, but for testing it can be handy to have both.) + + +# macros -------------------------------------------------------------------- + +#PNGDIR = ../..# for libpng-x.y.z/contrib/gregbook builds +PNGDIR = ../libpng-win32 +PNGINC = -I$(PNGDIR) +PNGLIBd = $(PNGDIR)/libpng.dll.a # dynamically linked +PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng + +#ZDIR = ../../../zlib-win32# for libpng-x.y.z/contrib/gregbook builds +ZDIR = ../zlib-win32 +ZINC = -I$(ZDIR) +ZLIBd = $(ZDIR)/libzdll.a +ZLIBs = $(ZDIR)/libz.a + +# change this to be the path where mingw32 installs its stuff: +W32DIR = +#W32DIR = /usr/local/cross-tools/i386-mingw32msvc +W32INC = -I$(W32DIR)/include +W32LIB = $(W32DIR)/lib/libuser32.a $(W32DIR)/lib/libgdi32.a + +CC = gcc +#CC = i386-mingw32msvc-gcc # e.g., Linux -> Win32 cross-compilation +LD = $(CC) +RM = rm -f +CFLAGS = -O -Wall $(INCS) $(MINGW_CCFLAGS) +# [note that -Wall is a gcc-specific compilation flag ("most warnings on")] +# [-ansi, -pedantic and -W can also be used] +LDFLAGS = $(MINGW_LDFLAGS) +O = .o +E = .exe + +INCS = $(PNGINC) $(ZINC) $(W32INC) +RLIBSd = $(PNGLIBd) $(ZLIBd) $(W32LIB) -lm +RLIBSs = $(PNGLIBs) $(ZLIBs) $(W32LIB) -lm +WLIBSd = $(PNGLIBd) $(ZLIBd) +WLIBSs = $(PNGLIBs) $(ZLIBs) + +RPNG = rpng-win +RPNG2 = rpng2-win +WPNG = wpng + +ROBJSd = $(RPNG)$(O) readpng.pic$(O) +ROBJS2d = $(RPNG2)$(O) readpng2.pic$(O) +WOBJSd = $(WPNG)$(O) writepng.pic$(O) + +RPNGs = $(RPNG)-static +RPNG2s = $(RPNG2)-static +WPNGs = $(WPNG)-static + +ROBJSs = $(RPNG)$(O) readpng$(O) +ROBJS2s = $(RPNG2)$(O) readpng2$(O) +WOBJSs = $(WPNG)$(O) writepng$(O) + +STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E) +DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + +EXES = $(STATIC_EXES) $(DYNAMIC_EXES) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +%.pic$(O): %.c + $(CC) -c $(CFLAGS) -DPNG_BUILD_DLL -o $@ $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNGs)$(E): $(ROBJSs) + $(LD) $(LDFLAGS) -o $@ $(ROBJSs) $(RLIBSs) + +$(RPNG)$(E): $(ROBJSd) + $(LD) $(LDFLAGS) -o $@ $(ROBJSd) $(RLIBSd) + +$(RPNG2s)$(E): $(ROBJS2s) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2s) $(RLIBSs) + +$(RPNG2)$(E): $(ROBJS2d) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2d) $(RLIBSd) + +$(WPNGs)$(E): $(WOBJSs) + $(LD) $(LDFLAGS) -o $@ $(WOBJSs) $(WLIBSs) + +$(WPNG)$(E): $(WOBJSd) + $(LD) $(LDFLAGS) -o $@ $(WOBJSd) $(WLIBSd) + +$(RPNG)$(O): $(RPNG).c readpng.h +$(RPNG2)$(O): $(RPNG2).c readpng2.h +$(WPNG)$(O): $(WPNG).c writepng.h + +readpng$(O) readpng.pic$(O): readpng.c readpng.h +readpng2$(O) readpng2.pic$(O): readpng2.c readpng2.h +writepng$(O) writepng.pic$(O): writepng.c writepng.h + + +# maintenance --------------------------------------------------------------- + +clean: + $(RM) $(EXES) + $(RM) $(ROBJSs) $(ROBJS2s) $(WOBJSs) + $(RM) $(ROBJSd) $(ROBJS2d) $(WOBJSd) diff --git a/extern/libpng/include/contrib/gregbook/Makefile.sgi b/extern/libpng/include/contrib/gregbook/Makefile.sgi new file mode 100644 index 0000000000..91623acf06 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/Makefile.sgi @@ -0,0 +1,104 @@ +# Sample makefile for rpng-x / rpng2-x / wpng for SGI using cc and make. +# Greg Roelofs +# Last modified: 7 March 2002 +# +# The programs built by this makefile are described in the book, +# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and +# Associates, 1999). Go buy a copy, eh? Buy some for friends +# and family, too. (Not that this is a blatant plug or anything.) +# +# Invoke this makefile from a shell prompt in the usual way; for example: +# +# make -f Makefile.sgi +# +# This makefile assumes libpng and zlib have already been built or downloaded +# and are both installed in /usr/local/{include,lib} (as indicated by the +# PNG* and Z* macros below). Edit as appropriate--choose only ONE each of +# the PNGINC, PNGLIB, ZINC and ZLIB lines. +# +# This makefile builds dynamically linked executables (against libpng and zlib, +# that is), but that can be changed by uncommenting the appropriate PNGLIB and +# ZLIB lines. + + +# macros -------------------------------------------------------------------- + +PNGINC = -I/usr/local/include/libpng15 +PNGLIB = -L/usr/local/lib -lpng15 # dynamically linked against libpng +#PNGLIB = /usr/local/lib/libpng15.a # statically linked against libpng +# or: +#PNGINC = -I../.. +#PNGLIB = -L../.. -lpng +#PNGLIB = ../../libpng.a + +ZINC = -I/usr/local/include +ZLIB = -L/usr/local/lib -lz # dynamically linked against zlib +#ZLIB = /usr/local/lib/libz.a # statically linked against zlib +#ZINC = -I../zlib +#ZLIB = -L../zlib -lz +#ZLIB = ../../../zlib/libz.a + +XINC = -I/usr/include/X11 # old-style, stock X distributions +XLIB = -L/usr/lib/X11 -lX11 +#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 +#XINC = -I/usr/X11R6/include # new X distributions (XFree86, etc.) +#XLIB = -L/usr/X11R6/lib -lX11 + +INCS = $(PNGINC) $(ZINC) $(XINC) +RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm +WLIBS = $(PNGLIB) $(ZLIB) + +CC = cc +LD = cc +RM = rm -f +# ABI must be the same as that used to build libpng. +ABI= +CFLAGS = $(ABI) -O -fullwarn $(INCS) +LDFLAGS = $(ABI) +O = .o +E = + +RPNG = rpng-x +RPNG2 = rpng2-x +WPNG = wpng + +ROBJS = $(RPNG)$(O) readpng$(O) +ROBJS2 = $(RPNG2)$(O) readpng2$(O) +WOBJS = $(WPNG)$(O) writepng$(O) + +EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNG)$(E): $(ROBJS) + $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBS) + +$(RPNG2)$(E): $(ROBJS2) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBS) + +$(WPNG)$(E): $(WOBJS) + $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBS) + +$(RPNG)$(O): $(RPNG).c readpng.h +$(RPNG2)$(O): $(RPNG2).c readpng2.h +$(WPNG)$(O): $(WPNG).c writepng.h + +readpng$(O): readpng.c readpng.h +readpng2$(O): readpng2.c readpng2.h +writepng$(O): writepng.c writepng.h + + +# maintenance --------------------------------------------------------------- + +clean: + $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS) diff --git a/extern/libpng/include/contrib/gregbook/Makefile.unx b/extern/libpng/include/contrib/gregbook/Makefile.unx new file mode 100644 index 0000000000..b52d8b6aa6 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/Makefile.unx @@ -0,0 +1,132 @@ +# Sample makefile for rpng-x / rpng2-x / wpng using gcc and make. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# The programs built by this makefile are described in the book, +# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and +# Associates, 1999). Go buy a copy, eh? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# Invoke this makefile from a shell prompt in the usual way; for example: +# +# make -f Makefile.unx +# +# This makefile assumes libpng and zlib have already been built or downloaded +# and are installed in /usr/local/{include,lib} or as otherwise indicated by +# the PNG* and Z* macros below. Edit as appropriate--choose only ONE each of +# the PNGINC, PNGLIBd, PNGLIBs, ZINC, ZLIBd and ZLIBs lines. +# +# This makefile builds both dynamically and statically linked executables +# (against libpng and zlib, that is), but that can be changed by modifying +# the "EXES =" line. (You need only one set, but for testing it can be handy +# to have both.) + + +# macros -------------------------------------------------------------------- + +#PNGDIR = /usr/local/lib +#PNGINC = -I/usr/local/include/libpng15 +#PNGLIBd = -L$(PNGDIR) -lpng15 # dynamically linked, installed libpng +#PNGLIBs = $(PNGDIR)/libpng15.a # statically linked, installed libpng +# or: +PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds +#PNGDIR = ../libpng +PNGINC = -I$(PNGDIR) +PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng15 # dynamically linked +PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng + +ZDIR = /usr/local/lib +#ZDIR = /usr/lib64 +ZINC = -I/usr/local/include +ZLIBd = -L$(ZDIR) -lz # dynamically linked against zlib +ZLIBs = $(ZDIR)/libz.a # statically linked against zlib +# or: +#ZDIR = ../zlib +#ZINC = -I$(ZDIR) +#ZLIBd = -Wl,-rpath,$(ZDIR) -L$(ZDIR) -lz # -rpath allows in-place testing +#ZLIBs = $(ZDIR)/libz.a + +#XINC = -I/usr/include # old-style, stock X distributions +#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX) +#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 +XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.) +XLIB = -L/usr/X11R6/lib -lX11 +#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64 + +INCS = $(PNGINC) $(ZINC) $(XINC) +RLIBSd = $(PNGLIBd) $(ZLIBd) $(XLIB) -lm +RLIBSs = $(PNGLIBs) $(ZLIBs) $(XLIB) -lm +WLIBSd = $(PNGLIBd) $(ZLIBd) -lm +WLIBSs = $(PNGLIBs) $(ZLIBs) + +CC = gcc +LD = gcc +RM = rm -f +CFLAGS = -O -Wall $(INCS) -DFEATURE_LOOP +# [note that -Wall is a gcc-specific compilation flag ("most warnings on")] +# [-ansi, -pedantic and -W can also be used] +LDFLAGS = +O = .o +E = + +RPNG = rpng-x +RPNG2 = rpng2-x +WPNG = wpng + +RPNGs = $(RPNG)-static +RPNG2s = $(RPNG2)-static +WPNGs = $(WPNG)-static + +ROBJS = $(RPNG)$(O) readpng$(O) +ROBJS2 = $(RPNG2)$(O) readpng2$(O) +WOBJS = $(WPNG)$(O) writepng$(O) + +STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E) +DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + +EXES = $(STATIC_EXES) $(DYNAMIC_EXES) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNGs)$(E): $(ROBJS) + $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSs) + +$(RPNG)$(E): $(ROBJS) + $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSd) + +$(RPNG2s)$(E): $(ROBJS2) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSs) + +$(RPNG2)$(E): $(ROBJS2) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSd) + +$(WPNGs)$(E): $(WOBJS) + $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSs) + +$(WPNG)$(E): $(WOBJS) + $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSd) + +$(RPNG)$(O): $(RPNG).c readpng.h +$(RPNG2)$(O): $(RPNG2).c readpng2.h +$(WPNG)$(O): $(WPNG).c writepng.h + +readpng$(O): readpng.c readpng.h +readpng2$(O): readpng2.c readpng2.h +writepng$(O): writepng.c writepng.h + + +# maintenance --------------------------------------------------------------- + +clean: + $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS) diff --git a/extern/libpng/include/contrib/gregbook/Makefile.w32 b/extern/libpng/include/contrib/gregbook/Makefile.w32 new file mode 100644 index 0000000000..3c0808593c --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/Makefile.w32 @@ -0,0 +1,113 @@ +# Sample makefile for rpng-win / rpng2-win / wpng using MSVC and NMAKE. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# The programs built by this makefile are described in the book, +# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and +# Associates, 1999). Go buy a copy, eh? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# Invoke this makefile from a DOS prompt window via: +# +# %devstudio%\vc\bin\vcvars32.bat +# nmake -nologo -f Makefile.w32 +# +# where %devstudio% is the installation directory for MSVC / DevStudio. If +# you get "environment out of space" errors, create a desktop shortcut with +# "c:\windows\command.com /e:4096" as the program command line and set the +# working directory to this directory. Then double-click to open the new +# DOS-prompt window with a bigger environment and retry the commands above. +# +# This makefile assumes libpng and zlib have already been built or downloaded +# and are in subdirectories at the same level as the current subdirectory +# (as indicated by the PNGPATH and ZPATH macros below). Edit as appropriate. +# +# Note that the names of the dynamic and static libpng and zlib libraries +# used below may change in later releases of the libraries. This makefile +# builds statically linked executables, but that can be changed by uncom- +# menting the appropriate PNGLIB and ZLIB lines. + +!include + + +# macros -------------------------------------------------------------------- + +PNGPATH = ../libpng +PNGINC = -I$(PNGPATH) +#PNGLIB = $(PNGPATH)/pngdll.lib +PNGLIB = $(PNGPATH)/libpng.lib + +ZPATH = ../zlib +ZINC = -I$(ZPATH) +#ZLIB = $(ZPATH)/zlibdll.lib +ZLIB = $(ZPATH)/zlibstat.lib + +WINLIBS = -defaultlib:user32.lib gdi32.lib +# ["real" apps may also need comctl32.lib, comdlg32.lib, winmm.lib, etc.] + +INCS = $(PNGINC) $(ZINC) +RLIBS = $(PNGLIB) $(ZLIB) $(WINLIBS) +WLIBS = $(PNGLIB) $(ZLIB) + +CC = cl +LD = link +RM = del +CFLAGS = -nologo -O -W3 $(INCS) $(cvars) +# [note that -W3 is an MSVC-specific compilation flag ("all warnings on")] +# [see %devstudio%\vc\include\win32.mak for cvars macro definition] +O = .obj +E = .exe + +RLDFLAGS = -nologo -subsystem:windows +WLDFLAGS = -nologo + +RPNG = rpng-win +RPNG2 = rpng2-win +WPNG = wpng + +ROBJS = $(RPNG)$(O) readpng$(O) +ROBJS2 = $(RPNG2)$(O) readpng2$(O) +WOBJS = $(WPNG)$(O) writepng$(O) + +EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNG)$(E): $(ROBJS) + $(LD) $(RLDFLAGS) -out:$@ $(ROBJS) $(RLIBS) + +$(RPNG2)$(E): $(ROBJS2) + $(LD) $(RLDFLAGS) -out:$@ $(ROBJS2) $(RLIBS) + +$(WPNG)$(E): $(WOBJS) + $(LD) $(WLDFLAGS) -out:$@ $(WOBJS) $(WLIBS) + +$(RPNG)$(O): $(RPNG).c readpng.h +$(RPNG2)$(O): $(RPNG2).c readpng2.h +$(WPNG)$(O): $(WPNG).c writepng.h + +readpng$(O): readpng.c readpng.h +readpng2$(O): readpng2.c readpng2.h +writepng$(O): writepng.c writepng.h + + +# maintenance --------------------------------------------------------------- + +clean: +# ideally we could just do this: +# $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS) +# ...but the Windows "DEL" command is none too bright, so: + $(RM) r*$(E) + $(RM) w*$(E) + $(RM) r*$(O) + $(RM) w*$(O) diff --git a/extern/libpng/include/contrib/gregbook/README b/extern/libpng/include/contrib/gregbook/README new file mode 100644 index 0000000000..6f8e079f21 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/README @@ -0,0 +1,186 @@ + =========================== + PNG: The Definitive Guide + =========================== + + Source Code + +Chapters 13, 14 and 15 of "PNG: The Definitive Guide" discuss three free, +cross-platform demo programs that show how to use the libpng reference +library: rpng, rpng2 and wpng. rpng and rpng2 are viewers; the first is +a very simple example that that shows how a standard file-viewer might use +libpng, while the second is designed to process streaming data and shows +how a web browser might be written. wpng is a simple command-line program +that reads binary PGM and PPM files (the ``raw'' grayscale and RGB subsets +of PBMPLUS/NetPBM) and converts them to PNG. + +The source code for all three demo programs currently compiles under +Unix, OpenVMS, and 32-bit Windows. (Special thanks to Martin Zinser, +zinser@decus.de, for making the necessary changes for OpenVMS and for +providing an appropriate build script.) Build instructions can be found +below. + +Files: + + README this file + LICENSE terms of distribution and reuse (BSD-like or GNU GPL) + COPYING GNU General Public License (GPL) + + Makefile.unx Unix makefile + Makefile.w32 Windows (MSVC) makefile + makevms.com OpenVMS build script + + rpng-win.c Windows front end for the basic viewer + rpng-x.c X Window System (Unix, OpenVMS) front end + readpng.c generic back end for the basic viewer + readpng.h header file for the basic viewer + + rpng2-win.c Windows front end for the progressive viewer + rpng2-x.c X front end for the progressive viewer + readpng2.c generic back end for the progressive viewer + readpng2.h header file for the progressive viewer + + wpng.c generic (text) front end for the converter + writepng.c generic back end for the converter + writepng.h header file for the converter + + toucan.png transparent PNG for testing (by Stefan Schneider) + +Note that, although the programs are designed to be functional, their +primary purpose is to illustrate how to use libpng to add PNG support to +other programs. As such, their user interfaces are crude and definitely +are not intended for everyday use. + +Please see http://www.libpng.org/pub/png/pngbook.html for further infor- +mation and links to the latest version of the source code, and Chapters +13-15 of the book for detailed discussion of the three programs. + +Greg Roelofs +http://pobox.com/~newt/greg_contact.html +16 March 2008 + + +BUILD INSTRUCTIONS + + - Prerequisites (in order of compilation): + + - zlib http://zlib.net/ + - libpng http://www.libpng.org/pub/png/libpng.html + - pngbook http://www.libpng.org/pub/png/book/sources.html + + The pngbook demo programs are explicitly designed to demonstrate proper + coding techniques for using the libpng reference library. As a result, + you need to download and build both zlib (on which libpng depends) and + libpng. A common build setup is to place the zlib, libpng and pngbook + subdirectory trees ("folders") in the same parent directory. Then the + libpng build can refer to files in ../zlib (or ..\zlib or [-.zlib]), + and similarly for the pngbook build. + + Note that all three packages are designed to be built from a command + line by default; those who wish to use a graphical or other integrated + development environments are on their own. + + + - Unix: + + Unpack the latest pngbook sources (which should correspond to this + README file) into a directory and change into that directory. + + Copy Makefile.unx to Makefile and edit the PNG* and Z* variables + appropriately (possibly also the X* variables if necessary). + + make + + There is no "install" target, so copy the three executables somewhere + in your path or run them from the current directory. All three will + print a basic usage screen when run without any command-line arguments; + see the book for more details. + + + - Windows: + + Unpack the latest pngbook sources (which should correspond to this + README file) into a folder, open a "DOS shell" or "command prompt" + or equivalent command-line window, and cd into the folder where you + unpacked the source code. + + For MSVC, set up the necessary environment variables by invoking + + %devstudio%\vc\bin\vcvars32.bat + + where where %devstudio% is the installation directory for MSVC / + DevStudio. If you get "environment out of space" errors under 95/98, + create a desktop shortcut with "c:\windows\command.com /e:4096" as + the program command line and set the working directory to the pngbook + directory. Then double-click to open the new DOS-prompt window with + a bigger environment and retry the commands above. + + Copy Makefile.w32 to Makefile and edit the PNGPATH and ZPATH variables + appropriately (possibly also the "INC" and "LIB" variables if needed). + Note that the names of the dynamic and static libpng and zlib libraries + used in the makefile may change in later releases of the libraries. + Also note that, as of libpng version 1.0.5, MSVC DLL builds do not work. + This makefile therefore builds statically linked executables, but if + the DLL problems ever get fixed, uncommenting the appropriate PNGLIB + and ZLIB lines will build dynamically linked executables instead. + + Do the build by typing + + nmake + + The result should be three executables: rpng-win.exe, rpng2-win.exe, + and wpng.exe. Copy them somewhere in your PATH or run them from the + current folder. Like the Unix versions, the two windowed programs + (rpng and rpng2) now display a usage screen in a console window when + invoked without command-line arguments; this is new behavior as of + the June 2001 release. Note that the programs use the Unix-style "-" + character to specify options, instead of the more common DOS/Windows + "/" character. (For example: "rpng2-win -bgpat 4 foo.png", not + "rpng2-win /bgpat 4 foo.png") + + + - OpenVMS: + + Unpack the pngbook sources into a subdirectory and change into that + subdirectory. + + Edit makevms.com appropriately, specifically the zpath and pngpath + variables. + + @makevms + + To run the programs, they probably first need to be set up as "foreign + symbols," with "disk" and "dir" set appropriately: + + $ rpng == "$disk:[dir]rpng-x.exe" + $ rpng2 == "$disk:[dir]rpng2-x.exe" + $ wpng == "$disk:[dir]wpng.exe" + + All three will print a basic usage screen when run without any command- + line arguments; see the book for more details. Note that the options + style is Unix-like, i.e., preceded by "-" rather than "/". + + +RUNNING THE PROGRAMS: (VERY) BRIEF INTRO + + rpng is a simple PNG viewer that can display transparent PNGs with a + specified background color; for example, + + rpng -bgcolor \#ff0000 toucan.png + + would display the image with a red background. rpng2 is a progressive + viewer that simulates a web browser in some respects; it can display + images against either a background color or a dynamically generated + background image. For example: + + rpng2 -bgpat 16 toucan.png + + wpng is a purely command-line image converter from binary PBMPLUS/NetPBM + format (.pgm or .ppm) to PNG; for example, + + wpng -time < toucan-notrans.ppm > toucan-notrans.png + + would convert the specified PPM file (using redirection) to PNG, auto- + matically setting the PNG modification-time chunk. + + All options can be abbreviated to the shortest unique value; for example, + "-bgc" for -bgcolor (versus "-bgp" for -bgpat), or "-g" for -gamma. diff --git a/extern/libpng/include/contrib/gregbook/makevms.com b/extern/libpng/include/contrib/gregbook/makevms.com new file mode 100644 index 0000000000..bd37dc0d77 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/makevms.com @@ -0,0 +1,132 @@ +$!------------------------------------------------------------------------------ +$! make "PNG: The Definitive Guide" demo programs (for X) under OpenVMS +$! +$! Script created by Martin Zinser for libpng; modified by Greg Roelofs +$! for standalone pngbook source distribution. +$! +$! +$! Set locations where zlib and libpng sources live. +$! +$ zpath = "" +$ pngpath = "" +$! +$ if f$search("[---.zlib]zlib.h").nes."" then zpath = "[---.zlib]" +$ if f$search("[--]png.h").nes."" then pngpath = "[--]" +$! +$ if f$search("[-.zlib]zlib.h").nes."" then zpath = "[-.zlib]" +$ if f$search("[-.libpng]png.h").nes."" then pngpath = "[-.libpng]" +$! +$ if zpath .eqs. "" +$ then +$ write sys$output "zlib include not found. Exiting..." +$ exit 2 +$ endif +$! +$ if pngpath .eqs. "" +$ then +$ write sys$output "libpng include not found. Exiting..." +$ exit 2 +$ endif +$! +$! Look for the compiler used. +$! +$ ccopt="/include=(''zpath',''pngpath')" +$ if f$getsyi("HW_MODEL").ge.1024 +$ then +$ ccopt = "/prefix=all"+ccopt +$ comp = "__decc__=1" +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ else +$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" +$ then +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs."" +$ then +$ comp = "__gcc__=1" +$ CC :== GCC +$ else +$ comp = "__vaxc__=1" +$ endif +$ else +$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include: +$ ccopt = "/decc/prefix=all"+ccopt +$ comp = "__decc__=1" +$ endif +$ endif +$ open/write lopt lib.opt +$ write lopt "''pngpath'libpng.olb/lib" +$ write lopt "''zpath'libz.olb/lib" +$ close lopt +$ open/write xopt x11.opt +$ write xopt "sys$library:decw$xlibshr.exe/share" +$ close xopt +$! +$! Build 'em. +$! +$ write sys$output "Compiling PNG book programs ..." +$ CALL MAKE readpng.OBJ "cc ''CCOPT' readpng" - + readpng.c readpng.h +$ CALL MAKE readpng2.OBJ "cc ''CCOPT' readpng2" - + readpng2.c readpng2.h +$ CALL MAKE writepng.OBJ "cc ''CCOPT' writepng" - + writepng.c writepng.h +$ write sys$output "Building rpng-x..." +$ CALL MAKE rpng-x.OBJ "cc ''CCOPT' rpng-x" - + rpng-x.c readpng.h +$ call make rpng-x.exe - + "LINK rpng-x,readpng,lib.opt/opt,x11.opt/opt" - + rpng-x.obj readpng.obj +$ write sys$output "Building rpng2-x..." +$ CALL MAKE rpng2-x.OBJ "cc ''CCOPT' rpng2-x" - + rpng2-x.c readpng2.h +$ call make rpng2-x.exe - + "LINK rpng2-x,readpng2,lib.opt/opt,x11.opt/opt" - + rpng2-x.obj readpng2.obj +$ write sys$output "Building wpng..." +$ CALL MAKE wpng.OBJ "cc ''CCOPT' wpng" - + wpng.c writepng.h +$ call make wpng.exe - + "LINK wpng,writepng,lib.opt/opt" - + wpng.obj writepng.obj +$ exit +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE diff --git a/extern/libpng/include/contrib/gregbook/readpng.c b/extern/libpng/include/contrib/gregbook/readpng.c new file mode 100644 index 0000000000..d72309fd19 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/readpng.c @@ -0,0 +1,305 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readpng.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#include +#include + +#include "png.h" /* libpng header; includes zlib.h */ +#include "readpng.h" /* typedefs, common macros, public prototypes */ + +/* future versions of libpng will provide this macro: */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + + +static png_structp png_ptr = NULL; +static png_infop info_ptr = NULL; + +png_uint_32 width, height; +int bit_depth, color_type; +uch *image_data = NULL; + + +void readpng_version_info(void) +{ + fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver); + fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", + ZLIB_VERSION, zlib_version); +} + + +/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ + +int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) +{ + uch sig[8]; + + + /* first do a quick check that the file really is a PNG image; could + * have used slightly more general png_sig_cmp() function instead */ + + fread(sig, 1, 8, infile); + if (png_sig_cmp(sig, 0, 8)) + return 1; /* bad signature */ + + + /* could pass pointers to user-defined error handlers instead of NULLs: */ + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + return 4; /* out of memory */ + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return 4; /* out of memory */ + } + + + /* we could create a second info struct here (end_info), but it's only + * useful if we want to keep pre- and post-IDAT chunk info separated + * (mainly for PNG-aware image editors and converters) */ + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 2; + } + + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ + + png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ + + + /* alternatively, could make separate calls to png_get_image_width(), + * etc., but want bit_depth and color_type for later [don't care about + * compression_type and filter_type => NULLs] */ + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + *pWidth = width; + *pHeight = height; + + + /* OK, that's all we need for now; return happy */ + + return 0; +} + + + + +/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; + * scales values to 8-bit if necessary */ + +int readpng_get_bgcolor(uch *red, uch *green, uch *blue) +{ + png_color_16p pBackground; + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 2; + } + + + if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) + return 1; + + /* it is not obvious from the libpng documentation, but this function + * takes a pointer to a pointer, and it always returns valid red, green + * and blue values, regardless of color_type: */ + + png_get_bKGD(png_ptr, info_ptr, &pBackground); + + + /* however, it always returns the raw bKGD data, regardless of any + * bit-depth transformations, so check depth and adjust if necessary */ + + if (bit_depth == 16) { + *red = pBackground->red >> 8; + *green = pBackground->green >> 8; + *blue = pBackground->blue >> 8; + } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + if (bit_depth == 1) + *red = *green = *blue = pBackground->gray? 255 : 0; + else if (bit_depth == 2) + *red = *green = *blue = (255/3) * pBackground->gray; + else /* bit_depth == 4 */ + *red = *green = *blue = (255/15) * pBackground->gray; + } else { + *red = (uch)pBackground->red; + *green = (uch)pBackground->green; + *blue = (uch)pBackground->blue; + } + + return 0; +} + + + + +/* display_exponent == LUT_exponent * CRT_exponent */ + +uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) +{ + double gamma; + png_uint_32 i, rowbytes; + png_bytepp row_pointers = NULL; + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return NULL; + } + + + /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, + * transparency chunks to full alpha channel; strip 16-bit-per-sample + * images to 8 bits per sample; and convert grayscale to RGB[A] */ + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (bit_depth == 16) + png_set_strip_16(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + + /* unlike the example in the libpng documentation, we have *no* idea where + * this file may have come from--so if it doesn't have a file gamma, don't + * do any correction ("do no harm") */ + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, display_exponent, gamma); + + + /* all transformations have been registered; now update info_ptr data, + * get rowbytes and channels, and allocate image memory */ + + png_read_update_info(png_ptr, info_ptr); + + *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); + *pChannels = (int)png_get_channels(png_ptr, info_ptr); + + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return NULL; + } + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + image_data = NULL; + return NULL; + } + + Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", + *pChannels, rowbytes, height)); + + + /* set the individual row_pointers to point at the correct offsets */ + + for (i = 0; i < height; ++i) + row_pointers[i] = image_data + i*rowbytes; + + + /* now we can go ahead and just read the whole image */ + + png_read_image(png_ptr, row_pointers); + + + /* and we're done! (png_read_end() can be omitted if no processing of + * post-IDAT text/time/etc. is desired) */ + + free(row_pointers); + row_pointers = NULL; + + png_read_end(png_ptr, NULL); + + return image_data; +} + + +void readpng_cleanup(int free_image_data) +{ + if (free_image_data && image_data) { + free(image_data); + image_data = NULL; + } + + if (png_ptr && info_ptr) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + png_ptr = NULL; + info_ptr = NULL; + } +} diff --git a/extern/libpng/include/contrib/gregbook/readpng.h b/extern/libpng/include/contrib/gregbook/readpng.h new file mode 100644 index 0000000000..fad9fe3b4c --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/readpng.h @@ -0,0 +1,88 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readpng.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b)? (a) : (b)) +# define MIN(a,b) ((a) < (b)? (a) : (b)) +#endif + +#ifdef DEBUG +# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} +#else +# define Trace(x) ; +#endif + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + + +/* prototypes for public functions in readpng.c */ + +void readpng_version_info(void); + +int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight); + +int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue); + +uch *readpng_get_image(double display_exponent, int *pChannels, + ulg *pRowbytes); + +void readpng_cleanup(int free_image_data); diff --git a/extern/libpng/include/contrib/gregbook/readpng2.c b/extern/libpng/include/contrib/gregbook/readpng2.c new file mode 100644 index 0000000000..1772a90653 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/readpng2.c @@ -0,0 +1,505 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program readpng2.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + + +#include /* for exit() prototype */ +#include + +#include +#include "png.h" /* libpng header from the local directory */ +#include "readpng2.h" /* typedefs, common macros, public prototypes */ + + +/* local prototypes */ + +static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr); +static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass); +static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr); +static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg); + + + + +void readpng2_version_info(void) +{ + fprintf(stderr, " Compiled with libpng %s; using libpng %s\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver); + + fprintf(stderr, " and with zlib %s; using zlib %s.\n", + ZLIB_VERSION, zlib_version); +} + + + + +int readpng2_check_sig(uch *sig, int num) +{ + return !png_sig_cmp(sig, 0, num); +} + + + + +/* returns 0 for success, 2 for libpng problem, 4 for out of memory */ + +int readpng2_init(mainprog_info *mainprog_ptr) +{ + png_structp png_ptr; /* note: temporary variables! */ + png_infop info_ptr; + + + /* could also replace libpng warning-handler (final NULL), but no need: */ + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, + readpng2_error_handler, NULL); + if (!png_ptr) + return 4; /* out of memory */ + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return 4; /* out of memory */ + } + + + /* we could create a second info struct here (end_info), but it's only + * useful if we want to keep pre- and post-IDAT chunk info separated + * (mainly for PNG-aware image editors and converters) */ + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function, unless an alternate error handler was installed-- + * but compatible error handlers must either use longjmp() themselves + * (as in this program) or exit immediately, so here we are: */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 2; + } + + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + /* prepare the reader to ignore all recognized chunks whose data won't be + * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT, + * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */ + { + /* These byte strings were copied from png.h. If a future libpng + * version recognizes more chunks, add them to this list. If a + * future version of readpng2.c recognizes more chunks, delete them + * from this list. */ + static /* const */ png_byte chunks_to_ignore[] = { + 99, 72, 82, 77, '\0', /* cHRM */ + 104, 73, 83, 84, '\0', /* hIST */ + 105, 67, 67, 80, '\0', /* iCCP */ + 105, 84, 88, 116, '\0', /* iTXt */ + 111, 70, 70, 115, '\0', /* oFFs */ + 112, 67, 65, 76, '\0', /* pCAL */ + 112, 72, 89, 115, '\0', /* pHYs */ + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 67, 65, 76, '\0', /* sCAL */ + 115, 80, 76, 84, '\0', /* sPLT */ + 115, 84, 69, 82, '\0', /* sTER */ + 116, 69, 88, 116, '\0', /* tEXt */ + 116, 73, 77, 69, '\0', /* tIME */ + 122, 84, 88, 116, '\0' /* zTXt */ + }; + + png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, + chunks_to_ignore, sizeof(chunks_to_ignore)/5); + } +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ + + + /* instead of doing png_init_io() here, now we set up our callback + * functions for progressive decoding */ + + png_set_progressive_read_fn(png_ptr, mainprog_ptr, + readpng2_info_callback, readpng2_row_callback, readpng2_end_callback); + + + /* make sure we save our pointers for use in readpng2_decode_data() */ + + mainprog_ptr->png_ptr = png_ptr; + mainprog_ptr->info_ptr = info_ptr; + + + /* and that's all there is to initialization */ + + return 0; +} + + + + +/* returns 0 for success, 2 for libpng (longjmp) problem */ + +int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length) +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + mainprog_ptr->png_ptr = NULL; + mainprog_ptr->info_ptr = NULL; + return 2; + } + + + /* hand off the next chunk of input data to libpng for decoding */ + + png_process_data(png_ptr, info_ptr, rawbuf, length); + + return 0; +} + + + + +static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) +{ + mainprog_info *mainprog_ptr; + int color_type, bit_depth; + png_uint_32 width, height; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double gamma; +#else + png_fixed_point gamma; +#endif + + + /* setjmp() doesn't make sense here, because we'd either have to exit(), + * longjmp() ourselves, or return control to libpng, which doesn't want + * to see us again. By not doing anything here, libpng will instead jump + * to readpng2_decode_data(), which can return an error value to the main + * program. */ + + + /* retrieve the pointer to our special-purpose struct, using the png_ptr + * that libpng passed back to us (i.e., not a global this time--there's + * no real difference for a single image, but for a multithreaded browser + * decoding several PNG images at the same time, one needs to avoid mixing + * up different images' structs) */ + + mainprog_ptr = png_get_progressive_ptr(png_ptr); + + if (mainprog_ptr == NULL) { /* we be hosed */ + fprintf(stderr, + "readpng2 error: main struct not recoverable in info_callback.\n"); + fflush(stderr); + return; + /* + * Alternatively, we could call our error-handler just like libpng + * does, which would effectively terminate the program. Since this + * can only happen if png_ptr gets redirected somewhere odd or the + * main PNG struct gets wiped, we're probably toast anyway. (If + * png_ptr itself is NULL, we would not have been called.) + */ + } + + + /* this is just like in the non-progressive case */ + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + mainprog_ptr->width = (ulg)width; + mainprog_ptr->height = (ulg)height; + + + /* since we know we've read all of the PNG file's "header" (i.e., up + * to IDAT), we can check for a background color here */ + + if (mainprog_ptr->need_bgcolor && + png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) + { + png_color_16p pBackground; + + /* it is not obvious from the libpng documentation, but this function + * takes a pointer to a pointer, and it always returns valid red, + * green and blue values, regardless of color_type: */ + png_get_bKGD(png_ptr, info_ptr, &pBackground); + + /* however, it always returns the raw bKGD data, regardless of any + * bit-depth transformations, so check depth and adjust if necessary */ + if (bit_depth == 16) { + mainprog_ptr->bg_red = pBackground->red >> 8; + mainprog_ptr->bg_green = pBackground->green >> 8; + mainprog_ptr->bg_blue = pBackground->blue >> 8; + } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + if (bit_depth == 1) + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = pBackground->gray? 255 : 0; + else if (bit_depth == 2) + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = (255/3) * pBackground->gray; + else /* bit_depth == 4 */ + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = (255/15) * pBackground->gray; + } else { + mainprog_ptr->bg_red = (uch)pBackground->red; + mainprog_ptr->bg_green = (uch)pBackground->green; + mainprog_ptr->bg_blue = (uch)pBackground->blue; + } + } + + + /* as before, let libpng expand palette images to RGB, low-bit-depth + * grayscale images to 8 bits, transparency chunks to full alpha channel; + * strip 16-bit-per-sample images to 8 bits per sample; and convert + * grayscale to RGB[A] */ + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (bit_depth == 16) + png_set_strip_16(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + + /* Unlike the basic viewer, which was designed to operate on local files, + * this program is intended to simulate a web browser--even though we + * actually read from a local file, too. But because we are pretending + * that most of the images originate on the Internet, we follow the recom- + * mendation of the sRGB proposal and treat unlabelled images (no gAMA + * chunk) as existing in the sRGB color space. That is, we assume that + * such images have a file gamma of 0.45455, which corresponds to a PC-like + * display system. This change in assumptions will have no effect on a + * PC-like system, but on a Mac, SGI, NeXT or other system with a non- + * identity lookup table, it will darken unlabelled images, which effec- + * tively favors images from PC-like systems over those originating on + * the local platform. Note that mainprog_ptr->display_exponent is the + * "gamma" value for the entire display system, i.e., the product of + * LUT_exponent and CRT_exponent. */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma); + else + png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455); +#else + if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma); + else + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455); +#endif + + /* we'll let libpng expand interlaced images, too */ + + mainprog_ptr->passes = png_set_interlace_handling(png_ptr); + + + /* all transformations have been registered; now update info_ptr data and + * then get rowbytes and channels */ + + png_read_update_info(png_ptr, info_ptr); + + mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); + mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr); + + + /* Call the main program to allocate memory for the image buffer and + * initialize windows and whatnot. (The old-style function-pointer + * invocation is used for compatibility with a few supposedly ANSI + * compilers that nevertheless barf on "fn_ptr()"-style syntax.) */ + + (*mainprog_ptr->mainprog_init)(); + + + /* and that takes care of initialization */ + + return; +} + + + + + +static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) +{ + mainprog_info *mainprog_ptr; + + + /* first check whether the row differs from the previous pass; if not, + * nothing to combine or display */ + + if (!new_row) + return; + + + /* retrieve the pointer to our special-purpose struct so we can access + * the old rows and image-display callback function */ + + mainprog_ptr = png_get_progressive_ptr(png_ptr); + + + /* save the pass number for optional use by the front end */ + + mainprog_ptr->pass = pass; + + + /* have libpng either combine the new row data with the existing row data + * from previous passes (if interlaced) or else just copy the new row + * into the main program's image buffer */ + + png_progressive_combine_row(png_ptr, mainprog_ptr->row_pointers[row_num], + new_row); + + + /* finally, call the display routine in the main program with the number + * of the row we just updated */ + + (*mainprog_ptr->mainprog_display_row)(row_num); + + + /* and we're ready for more */ + + return; +} + + + + + +static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr) +{ + mainprog_info *mainprog_ptr; + + + /* retrieve the pointer to our special-purpose struct */ + + mainprog_ptr = png_get_progressive_ptr(png_ptr); + + + /* let the main program know that it should flush any buffered image + * data to the display now and set a "done" flag or whatever, but note + * that it SHOULD NOT DESTROY THE PNG STRUCTS YET--in other words, do + * NOT call readpng2_cleanup() either here or in the finish_display() + * routine; wait until control returns to the main program via + * readpng2_decode_data() */ + + (*mainprog_ptr->mainprog_finish_display)(); + + + /* all done */ + + return; +} + + + + + +void readpng2_cleanup(mainprog_info *mainprog_ptr) +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + if (png_ptr && info_ptr) + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + mainprog_ptr->png_ptr = NULL; + mainprog_ptr->info_ptr = NULL; +} + + + + + +static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg) +{ + mainprog_info *mainprog_ptr; + + /* This function, aside from the extra step of retrieving the "error + * pointer" (below) and the fact that it exists within the application + * rather than within libpng, is essentially identical to libpng's + * default error handler. The second point is critical: since both + * setjmp() and longjmp() are called from the same code, they are + * guaranteed to have compatible notions of how big a jmp_buf is, + * regardless of whether _BSD_SOURCE or anything else has (or has not) + * been defined. */ + + fprintf(stderr, "readpng2 libpng error: %s\n", msg); + fflush(stderr); + + mainprog_ptr = png_get_error_ptr(png_ptr); + if (mainprog_ptr == NULL) { /* we are completely hosed now */ + fprintf(stderr, + "readpng2 severe error: jmpbuf not recoverable; terminating.\n"); + fflush(stderr); + exit(99); + } + + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ + longjmp(mainprog_ptr->jmpbuf, 1); +} diff --git a/extern/libpng/include/contrib/gregbook/readpng2.h b/extern/libpng/include/contrib/gregbook/readpng2.h new file mode 100644 index 0000000000..6b3660d7c1 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/readpng2.h @@ -0,0 +1,116 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program readpng2.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b)? (a) : (b)) +# define MIN(a,b) ((a) < (b)? (a) : (b)) +#endif + +#ifdef DEBUG +# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} +#else +# define Trace(x) ; +#endif + +enum rpng2_states { + kPreInit = 0, + kWindowInit, + kDone +}; + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +typedef struct _mainprog_info { + double display_exponent; + ulg width; + ulg height; + void *png_ptr; + void *info_ptr; + void (*mainprog_init)(void); + void (*mainprog_display_row)(ulg row_num); + void (*mainprog_finish_display)(void); + uch *image_data; + uch **row_pointers; + jmp_buf jmpbuf; + int passes; /* not used */ + int pass; + int rowbytes; + int channels; + int need_bgcolor; + int state; + uch bg_red; + uch bg_green; + uch bg_blue; +} mainprog_info; + + +/* prototypes for public functions in readpng2.c */ + +void readpng2_version_info(void); + +int readpng2_check_sig(uch *sig, int num); + +int readpng2_init(mainprog_info *mainprog_ptr); + +int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length); + +void readpng2_cleanup(mainprog_info *mainprog_ptr); diff --git a/extern/libpng/include/contrib/gregbook/readppm.c b/extern/libpng/include/contrib/gregbook/readppm.c new file mode 100644 index 0000000000..be9a56d95f --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/readppm.c @@ -0,0 +1,179 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readppm.c + + --------------------------------------------------------------------------- + + This is a special-purpose replacement for readpng.c that allows binary + PPM files to be used in place of PNG images. + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#include +#include + +#include "readpng.h" /* typedefs, common macros, public prototypes */ + + +ulg width, height; +int bit_depth, color_type, channels; +uch *image_data = NULL; +FILE *saved_infile; + + +void readpng_version_info() +{ + fprintf(stderr, " Compiled without libpng, zlib or PBMPLUS/NetPBM.\n"); +} + + +/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ + +int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) +{ + static uch ppmline[256]; + int maxval; + + + saved_infile = infile; + + fgets(ppmline, 256, infile); + if (ppmline[0] != 'P' || ppmline[1] != '6') { + fprintf(stderr, "ERROR: not a PPM file\n"); + return 1; + } + /* possible color types: P5 = grayscale (0), P6 = RGB (2), P8 = RGBA (6) */ + if (ppmline[1] == '6') { + color_type = 2; + channels = 3; + } else if (ppmline[1] == '8') { + color_type = 6; + channels = 4; + } else /* if (ppmline[1] == '5') */ { + color_type = 0; + channels = 1; + } + + do { + fgets(ppmline, 256, infile); + } while (ppmline[0] == '#'); + sscanf(ppmline, "%lu %lu", &width, &height); + + do { + fgets(ppmline, 256, infile); + } while (ppmline[0] == '#'); + sscanf(ppmline, "%d", &maxval); + if (maxval != 255) { + fprintf(stderr, "ERROR: maxval = %d\n", maxval); + return 2; + } + bit_depth = 8; + + *pWidth = width; + *pHeight = height; + + return 0; +} + + + + +/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; + * scales values to 8-bit if necessary */ + +int readpng_get_bgcolor(uch *red, uch *green, uch *blue) +{ + return 1; +} + + + + +/* display_exponent == LUT_exponent * CRT_exponent */ + +uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) +{ + ulg rowbytes; + + + /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, + * transparency chunks to full alpha channel; strip 16-bit-per-sample + * images to 8 bits per sample; and convert grayscale to RGB[A] */ + + /* GRR WARNING: grayscale needs to be expanded and channels reset! */ + + *pRowbytes = rowbytes = channels*width; + *pChannels = channels; + + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { + return NULL; + } + + Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height)); + + + /* now we can go ahead and just read the whole image */ + + fread(image_data, 1L, rowbytes*height, saved_infile); + + + return image_data; +} + + +void readpng_cleanup(int free_image_data) +{ + if (free_image_data && image_data) { + free(image_data); + image_data = NULL; + } +} diff --git a/extern/libpng/include/contrib/gregbook/rpng-win.c b/extern/libpng/include/contrib/gregbook/rpng-win.c new file mode 100644 index 0000000000..f53ddc8ece --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/rpng-win.c @@ -0,0 +1,728 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program rpng-win.c + + This program decodes and displays PNG images, with gamma correction and + optionally with a user-specified background color (in case the image has + transparency). It is very nearly the most basic PNG viewer possible. + This version is for 32-bit Windows; it may compile under 16-bit Windows + with a little tweaking (or maybe not). + + to do: + - handle quoted command-line args (especially filenames with spaces) + - have minimum window width: oh well + - use %.1023s to simplify truncation of title-bar string? + + --------------------------------------------------------------------------- + + Changelog: + - 1.00: initial public release + - 1.01: modified to allow abbreviated options; fixed long/ulong mis- + match; switched to png_jmpbuf() macro + - 1.02: added extra set of parentheses to png_jmpbuf() macro; fixed + command-line parsing bug + - 1.10: enabled "message window"/console (thanks to David Geldreich) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed improper display of usage screen on PNG error(s) + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng-win" +#define LONGNAME "Simple PNG Viewer for Windows" +#define VERSION "2.01 of 16 March 2008" + +#include +#include +#include +#include +#include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else +#include /* only for _getch() */ +#endif + +/* #define DEBUG : this enables the Trace() macros */ + +#include "readpng.h" /* typedefs, common macros, readpng prototypes */ + + +/* could just include png.h, but this macro is the only thing we need + * (name and typedefs changed to local versions); note that side effects + * only happen with alpha (which could easily be avoided with + * "ush acopy = (alpha);") */ + +#define alpha_composite(composite, fg, alpha, bg) { \ + ush temp = ((ush)(fg)*(ush)(alpha) + \ + (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ + (composite) = (uch)((temp + (temp >> 8)) >> 8); \ +} + + +/* local prototypes */ +static int rpng_win_create_window(HINSTANCE hInst, int showmode); +static int rpng_win_display_image(void); +static void rpng_win_cleanup(void); +LRESULT CALLBACK rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM); + + +static char titlebar[1024]; +static char *progname = PROGNAME; +static char *appname = LONGNAME; +static char *filename; +static FILE *infile; + +static char *bgstr; +static uch bg_red=0, bg_green=0, bg_blue=0; + +static double display_exponent; + +static ulg image_width, image_height, image_rowbytes; +static int image_channels; +static uch *image_data; + +/* Windows-specific variables */ +static ulg wimage_rowbytes; +static uch *dib; +static uch *wimage_data; +static BITMAPINFOHEADER *bmih; + +static HWND global_hwnd; + + + + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) +{ + char *args[1024]; /* arbitrary limit, but should suffice */ + char *p, *q, **argv = args; + int argc = 0; + int rc, alen, flen; + int error = 0; + int have_bg = FALSE; + double LUT_exponent; /* just the lookup table */ + double CRT_exponent = 2.2; /* just the monitor */ + double default_display_exponent; /* whole display system */ + MSG msg; + + + filename = (char *)NULL; + +#ifndef __CYGWIN__ + /* First reenable console output, which normally goes to the bit bucket + * for windowed apps. Closing the console window will terminate the + * app. Thanks to David.Geldreich@realviz.com for supplying the magical + * incantation. */ + + AllocConsole(); + freopen("CONOUT$", "a", stderr); + freopen("CONOUT$", "a", stdout); +#endif + + + /* Next set the default value for our display-system exponent, i.e., + * the product of the CRT exponent and the exponent corresponding to + * the frame-buffer's lookup table (LUT), if any. This is not an + * exhaustive list of LUT values (e.g., OpenStep has a lot of weird + * ones), but it should cover 99% of the current possibilities. And + * yes, these ifdefs are completely wasted in a Windows program... */ + +#if defined(NeXT) + LUT_exponent = 1.0 / 2.2; + /* + if (some_next_function_that_returns_gamma(&next_gamma)) + LUT_exponent = 1.0 / next_gamma; + */ +#elif defined(sgi) + LUT_exponent = 1.0 / 1.7; + /* there doesn't seem to be any documented function to get the + * "gamma" value, so we do it the hard way */ + infile = fopen("/etc/config/system.glGammaVal", "r"); + if (infile) { + double sgi_gamma; + + fgets(tmpline, 80, infile); + fclose(infile); + sgi_gamma = atof(tmpline); + if (sgi_gamma > 0.0) + LUT_exponent = 1.0 / sgi_gamma; + } +#elif defined(Macintosh) + LUT_exponent = 1.8 / 2.61; + /* + if (some_mac_function_that_returns_gamma(&mac_gamma)) + LUT_exponent = mac_gamma / 2.61; + */ +#else + LUT_exponent = 1.0; /* assume no LUT: most PCs */ +#endif + + /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ + default_display_exponent = LUT_exponent * CRT_exponent; + + + /* If the user has set the SCREEN_GAMMA environment variable as suggested + * (somewhat imprecisely) in the libpng documentation, use that; otherwise + * use the default value we just calculated. Either way, the user may + * override this via a command-line option. */ + + if ((p = getenv("SCREEN_GAMMA")) != NULL) + display_exponent = atof(p); + else + display_exponent = default_display_exponent; + + + /* Windows really hates command lines, so we have to set up our own argv. + * Note that we do NOT bother with quoted arguments here, so don't use + * filenames with spaces in 'em! */ + + argv[argc++] = PROGNAME; + p = cmd; + for (;;) { + if (*p == ' ') + while (*++p == ' ') + ; + /* now p points at the first non-space after some spaces */ + if (*p == '\0') + break; /* nothing after the spaces: done */ + argv[argc++] = q = p; + while (*q && *q != ' ') + ++q; + /* now q points at a space or the end of the string */ + if (*q == '\0') + break; /* last argv already terminated; quit */ + *q = '\0'; /* change space to terminator */ + p = q + 1; + } + argv[argc] = NULL; /* terminate the argv array itself */ + + + /* Now parse the command line for options and the PNG filename. */ + + while (*++argv && !error) { + if (!strncmp(*argv, "-gamma", 2)) { + if (!*++argv) + ++error; + else { + display_exponent = atof(*argv); + if (display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 2)) { + if (!*++argv) + ++error; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else + have_bg = TRUE; + } + } else { + if (**argv != '-') { + filename = *argv; + if (argv[1]) /* shouldn't be any more args after filename */ + ++error; + } else + ++error; /* not expecting any other options */ + } + } + + if (!filename) + ++error; + + + /* print usage screen if any errors up to this point */ + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); + readpng_version_info(); + fprintf(stderr, "\n" + "Usage: %s [-gamma exp] [-bgcolor bg] file.png\n" + " exp \ttransfer-function exponent (``gamma'') of the display\n" + "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" + "\t\t to the product of the lookup-table exponent (varies)\n" + "\t\t and the CRT exponent (usually 2.2); must be positive\n" + " bg \tdesired background color in 7-character hex RGB format\n" + "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" + "\t\t used with transparent images\n" + "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" +#ifndef __CYGWIN__ + "Press Q or Esc to quit this usage screen.\n" +#endif + "\n", PROGNAME, default_display_exponent); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(1); + } + + + if (!(infile = fopen(filename, "rb"))) { + fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); + ++error; + } else { + if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) { + switch (rc) { + case 1: + fprintf(stderr, PROGNAME + ": [%s] is not a PNG file: incorrect signature\n", + filename); + break; + case 2: + fprintf(stderr, PROGNAME + ": [%s] has bad IHDR (libpng longjmp)\n", filename); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown readpng_init() error\n"); + break; + } + ++error; + } + if (error) + fclose(infile); + } + + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(2); + } else { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ + fprintf(stderr, + "\n [console window: closing this window will terminate %s]\n\n", + PROGNAME); +#endif + } + + + /* set the title-bar string, but make sure buffer doesn't overflow */ + + alen = strlen(appname); + flen = strlen(filename); + if (alen + flen + 3 > 1023) + sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); + else + sprintf(titlebar, "%s: %s", appname, filename); + + + /* if the user didn't specify a background color on the command line, + * check for one in the PNG file--if not, the initialized values of 0 + * (black) will be used */ + + if (have_bg) { + unsigned r, g, b; /* this approach quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + bg_red = (uch)r; + bg_green = (uch)g; + bg_blue = (uch)b; + } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) { + readpng_cleanup(TRUE); + fprintf(stderr, PROGNAME + ": libpng error while checking for background color\n"); + exit(2); + } + + + /* do the basic Windows initialization stuff, make the window and fill it + * with the background color */ + + if (rpng_win_create_window(hInst, showmode)) + exit(2); + + + /* decode the image, all at once */ + + Trace((stderr, "calling readpng_get_image()\n")) + image_data = readpng_get_image(display_exponent, &image_channels, + &image_rowbytes); + Trace((stderr, "done with readpng_get_image()\n")) + + + /* done with PNG file, so clean up to minimize memory usage (but do NOT + * nuke image_data!) */ + + readpng_cleanup(FALSE); + fclose(infile); + + if (!image_data) { + fprintf(stderr, PROGNAME ": unable to decode PNG image\n"); + exit(3); + } + + + /* display image (composite with background if requested) */ + + Trace((stderr, "calling rpng_win_display_image()\n")) + if (rpng_win_display_image()) { + free(image_data); + exit(4); + } + Trace((stderr, "done with rpng_win_display_image()\n")) + + + /* wait for the user to tell us when to quit */ + + printf( +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); + fflush(stdout); + + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + + /* OK, we're done: clean up all image and Windows resources and go away */ + + rpng_win_cleanup(); + + return msg.wParam; +} + + + + + +static int rpng_win_create_window(HINSTANCE hInst, int showmode) +{ + uch *dest; + int extra_width, extra_height; + ulg i, j; + WNDCLASSEX wndclass; + + +/*--------------------------------------------------------------------------- + Allocate memory for the display-specific version of the image (round up + to multiple of 4 for Windows DIB). + ---------------------------------------------------------------------------*/ + + wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2; + + if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + + wimage_rowbytes*image_height))) + { + return 4; /* fail */ + } + +/*--------------------------------------------------------------------------- + Initialize the DIB. Negative height means to use top-down BMP ordering + (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8 + implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values + directly => wimage_data begins immediately after BMP header. + ---------------------------------------------------------------------------*/ + + memset(dib, 0, sizeof(BITMAPINFOHEADER)); + bmih = (BITMAPINFOHEADER *)dib; + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = image_width; + bmih->biHeight = -((long)image_height); + bmih->biPlanes = 1; + bmih->biBitCount = 24; + bmih->biCompression = 0; + wimage_data = dib + sizeof(BITMAPINFOHEADER); + +/*--------------------------------------------------------------------------- + Fill in background color (black by default); data are in BGR order. + ---------------------------------------------------------------------------*/ + + for (j = 0; j < image_height; ++j) { + dest = wimage_data + j*wimage_rowbytes; + for (i = image_width; i > 0; --i) { + *dest++ = bg_blue; + *dest++ = bg_green; + *dest++ = bg_red; + } + } + +/*--------------------------------------------------------------------------- + Set the window parameters. + ---------------------------------------------------------------------------*/ + + memset(&wndclass, 0, sizeof(wndclass)); + + wndclass.cbSize = sizeof(wndclass); + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = rpng_win_wndproc; + wndclass.hInstance = hInst; + wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = progname; + wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + RegisterClassEx(&wndclass); + +/*--------------------------------------------------------------------------- + Finally, create the window. + ---------------------------------------------------------------------------*/ + + extra_width = 2*(GetSystemMetrics(SM_CXBORDER) + + GetSystemMetrics(SM_CXDLGFRAME)); + extra_height = 2*(GetSystemMetrics(SM_CYBORDER) + + GetSystemMetrics(SM_CYDLGFRAME)) + + GetSystemMetrics(SM_CYCAPTION); + + global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width, + image_height+extra_height, NULL, NULL, hInst, NULL); + + ShowWindow(global_hwnd, showmode); + UpdateWindow(global_hwnd); + + return 0; + +} /* end function rpng_win_create_window() */ + + + + + +static int rpng_win_display_image() +{ + uch *src, *dest; + uch r, g, b, a; + ulg i, row, lastrow; + RECT rect; + + + Trace((stderr, "beginning display loop (image_channels == %d)\n", + image_channels)) + Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n", + image_width, image_rowbytes, wimage_rowbytes)) + + +/*--------------------------------------------------------------------------- + Blast image data to buffer. This whole routine takes place before the + message loop begins, so there's no real point in any pseudo-progressive + display... + ---------------------------------------------------------------------------*/ + + for (lastrow = row = 0; row < image_height; ++row) { + src = image_data + row*image_rowbytes; + dest = wimage_data + row*wimage_rowbytes; + if (image_channels == 3) { + for (i = image_width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + *dest++ = b; + *dest++ = g; /* note reverse order */ + *dest++ = r; + } + } else /* if (image_channels == 4) */ { + for (i = image_width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (a == 255) { + *dest++ = b; + *dest++ = g; + *dest++ = r; + } else if (a == 0) { + *dest++ = bg_blue; + *dest++ = bg_green; + *dest++ = bg_red; + } else { + /* this macro (copied from png.h) composites the + * foreground and background values and puts the + * result into the first argument; there are no + * side effects with the first argument */ + alpha_composite(*dest++, b, a, bg_blue); + alpha_composite(*dest++, g, a, bg_green); + alpha_composite(*dest++, r, a, bg_red); + } + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + rect.left = 0L; + rect.top = (LONG)lastrow; + rect.right = (LONG)image_width; /* possibly off by one? */ + rect.bottom = (LONG)lastrow + 16L; /* possibly off by one? */ + InvalidateRect(global_hwnd, &rect, FALSE); + UpdateWindow(global_hwnd); /* similar to XFlush() */ + lastrow = row + 1; + } + } + + Trace((stderr, "calling final image-flush routine\n")) + if (lastrow < image_height) { + rect.left = 0L; + rect.top = (LONG)lastrow; + rect.right = (LONG)image_width; /* possibly off by one? */ + rect.bottom = (LONG)image_height; /* possibly off by one? */ + InvalidateRect(global_hwnd, &rect, FALSE); + UpdateWindow(global_hwnd); /* similar to XFlush() */ + } + +/* + last param determines whether or not background is wiped before paint + InvalidateRect(global_hwnd, NULL, TRUE); + UpdateWindow(global_hwnd); + */ + + return 0; +} + + + + + +static void rpng_win_cleanup() +{ + if (image_data) { + free(image_data); + image_data = NULL; + } + + if (dib) { + free(dib); + dib = NULL; + } +} + + + + + +LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP) +{ + HDC hdc; + PAINTSTRUCT ps; + int rc; + + switch (iMsg) { + case WM_CREATE: + /* one-time processing here, if any */ + return 0; + + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + /* dest */ + rc = StretchDIBits(hdc, 0, 0, image_width, image_height, + /* source */ + 0, 0, image_width, image_height, + wimage_data, (BITMAPINFO *)bmih, + /* iUsage: no clue */ + 0, SRCCOPY); + EndPaint(hwnd, &ps); + return 0; + + /* wait for the user to tell us when to quit */ + case WM_CHAR: + switch (wP) { /* only need one, so ignore repeat count */ + case 'q': + case 'Q': + case 0x1B: /* Esc key */ + PostQuitMessage(0); + } + return 0; + + case WM_LBUTTONDOWN: /* another way of quitting */ + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hwnd, iMsg, wP, lP); +} diff --git a/extern/libpng/include/contrib/gregbook/rpng-x.c b/extern/libpng/include/contrib/gregbook/rpng-x.c new file mode 100644 index 0000000000..e821cfb3d7 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/rpng-x.c @@ -0,0 +1,904 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program rpng-x.c + + This program decodes and displays PNG images, with gamma correction and + optionally with a user-specified background color (in case the image has + transparency). It is very nearly the most basic PNG viewer possible. + This version is for the X Window System (tested by author under Unix and + by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking). + + to do: + - 8-bit (colormapped) X support + - use %.1023s to simplify truncation of title-bar string? + + --------------------------------------------------------------------------- + + Changelog: + - 1.01: initial public release + - 1.02: modified to allow abbreviated options; fixed long/ulong mis- + match; switched to png_jmpbuf() macro + - 1.10: added support for non-default visuals; fixed X pixel-conversion + - 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed + command-line parsing bug + - 1.12: fixed some small X memory leaks (thanks to François Petitjean) + - 1.13: fixed XFreeGC() crash bug (thanks to Patrick Welche) + - 1.14: added support for X resources (thanks to Gerhard Niklasch) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed improper display of usage screen on PNG error(s) + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng-x" +#define LONGNAME "Simple PNG Viewer for X" +#define VERSION "2.01 of 16 March 2008" +#define RESNAME "rpng" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* #define DEBUG : this enables the Trace() macros */ + +#include "readpng.h" /* typedefs, common macros, readpng prototypes */ + + +/* could just include png.h, but this macro is the only thing we need + * (name and typedefs changed to local versions); note that side effects + * only happen with alpha (which could easily be avoided with + * "ush acopy = (alpha);") */ + +#define alpha_composite(composite, fg, alpha, bg) { \ + ush temp = ((ush)(fg)*(ush)(alpha) + \ + (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ + (composite) = (uch)((temp + (temp >> 8)) >> 8); \ +} + + +/* local prototypes */ +static int rpng_x_create_window(void); +static int rpng_x_display_image(void); +static void rpng_x_cleanup(void); +static int rpng_x_msb(ulg u32val); + + +static char titlebar[1024], *window_name = titlebar; +static char *appname = LONGNAME; +static char *icon_name = PROGNAME; +static char *res_name = RESNAME; +static char *res_class = RESCLASS; +static char *filename; +static FILE *infile; + +static char *bgstr; +static uch bg_red=0, bg_green=0, bg_blue=0; + +static double display_exponent; + +static ulg image_width, image_height, image_rowbytes; +static int image_channels; +static uch *image_data; + +/* X-specific variables */ +static char *displayname; +static XImage *ximage; +static Display *display; +static int depth; +static Visual *visual; +static XVisualInfo *visual_list; +static int RShift, GShift, BShift; +static ulg RMask, GMask, BMask; +static Window window; +static GC gc; +static Colormap colormap; + +static int have_nondefault_visual = FALSE; +static int have_colormap = FALSE; +static int have_window = FALSE; +static int have_gc = FALSE; +/* +ulg numcolors=0, pixels[256]; +ush reds[256], greens[256], blues[256]; + */ + + + + +int main(int argc, char **argv) +{ +#ifdef sgi + char tmpline[80]; +#endif + char *p; + int rc, alen, flen; + int error = 0; + int have_bg = FALSE; + double LUT_exponent; /* just the lookup table */ + double CRT_exponent = 2.2; /* just the monitor */ + double default_display_exponent; /* whole display system */ + XEvent e; + KeySym k; + + + displayname = (char *)NULL; + filename = (char *)NULL; + + + /* First set the default value for our display-system exponent, i.e., + * the product of the CRT exponent and the exponent corresponding to + * the frame-buffer's lookup table (LUT), if any. This is not an + * exhaustive list of LUT values (e.g., OpenStep has a lot of weird + * ones), but it should cover 99% of the current possibilities. */ + +#if defined(NeXT) + LUT_exponent = 1.0 / 2.2; + /* + if (some_next_function_that_returns_gamma(&next_gamma)) + LUT_exponent = 1.0 / next_gamma; + */ +#elif defined(sgi) + LUT_exponent = 1.0 / 1.7; + /* there doesn't seem to be any documented function to get the + * "gamma" value, so we do it the hard way */ + infile = fopen("/etc/config/system.glGammaVal", "r"); + if (infile) { + double sgi_gamma; + + fgets(tmpline, 80, infile); + fclose(infile); + sgi_gamma = atof(tmpline); + if (sgi_gamma > 0.0) + LUT_exponent = 1.0 / sgi_gamma; + } +#elif defined(Macintosh) + LUT_exponent = 1.8 / 2.61; + /* + if (some_mac_function_that_returns_gamma(&mac_gamma)) + LUT_exponent = mac_gamma / 2.61; + */ +#else + LUT_exponent = 1.0; /* assume no LUT: most PCs */ +#endif + + /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ + default_display_exponent = LUT_exponent * CRT_exponent; + + + /* If the user has set the SCREEN_GAMMA environment variable as suggested + * (somewhat imprecisely) in the libpng documentation, use that; otherwise + * use the default value we just calculated. Either way, the user may + * override this via a command-line option. */ + + if ((p = getenv("SCREEN_GAMMA")) != NULL) + display_exponent = atof(p); + else + display_exponent = default_display_exponent; + + + /* Now parse the command line for options and the PNG filename. */ + + while (*++argv && !error) { + if (!strncmp(*argv, "-display", 2)) { + if (!*++argv) + ++error; + else + displayname = *argv; + } else if (!strncmp(*argv, "-gamma", 2)) { + if (!*++argv) + ++error; + else { + display_exponent = atof(*argv); + if (display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 2)) { + if (!*++argv) + ++error; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else + have_bg = TRUE; + } + } else { + if (**argv != '-') { + filename = *argv; + if (argv[1]) /* shouldn't be any more args after filename */ + ++error; + } else + ++error; /* not expecting any other options */ + } + } + + if (!filename) + ++error; + + + /* print usage screen if any errors up to this point */ + + if (error) { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); + readpng_version_info(); + fprintf(stderr, "\n" + "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n" + " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" + " exp \ttransfer-function exponent (``gamma'') of the display\n" + "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" + "\t\t to the product of the lookup-table exponent (varies)\n" + "\t\t and the CRT exponent (usually 2.2); must be positive\n" + " bg \tdesired background color in 7-character hex RGB format\n" + "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" + "\t\t used with transparent images\n" + "\nPress Q, Esc or mouse button 1 (within image window, after image\n" + "is displayed) to quit.\n" + "\n", PROGNAME, default_display_exponent); + exit(1); + } + + + if (!(infile = fopen(filename, "rb"))) { + fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); + ++error; + } else { + if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) { + switch (rc) { + case 1: + fprintf(stderr, PROGNAME + ": [%s] is not a PNG file: incorrect signature\n", + filename); + break; + case 2: + fprintf(stderr, PROGNAME + ": [%s] has bad IHDR (libpng longjmp)\n", filename); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown readpng_init() error\n"); + break; + } + ++error; + } else { + display = XOpenDisplay(displayname); + if (!display) { + readpng_cleanup(TRUE); + fprintf(stderr, PROGNAME ": can't open X display [%s]\n", + displayname? displayname : "default"); + ++error; + } + } + if (error) + fclose(infile); + } + + + if (error) { + fprintf(stderr, PROGNAME ": aborting.\n"); + exit(2); + } + + + /* set the title-bar string, but make sure buffer doesn't overflow */ + + alen = strlen(appname); + flen = strlen(filename); + if (alen + flen + 3 > 1023) + sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); + else + sprintf(titlebar, "%s: %s", appname, filename); + + + /* if the user didn't specify a background color on the command line, + * check for one in the PNG file--if not, the initialized values of 0 + * (black) will be used */ + + if (have_bg) { + unsigned r, g, b; /* this approach quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + bg_red = (uch)r; + bg_green = (uch)g; + bg_blue = (uch)b; + } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) { + readpng_cleanup(TRUE); + fprintf(stderr, PROGNAME + ": libpng error while checking for background color\n"); + exit(2); + } + + + /* do the basic X initialization stuff, make the window and fill it + * with the background color */ + + if (rpng_x_create_window()) + exit(2); + + + /* decode the image, all at once */ + + Trace((stderr, "calling readpng_get_image()\n")) + image_data = readpng_get_image(display_exponent, &image_channels, + &image_rowbytes); + Trace((stderr, "done with readpng_get_image()\n")) + + + /* done with PNG file, so clean up to minimize memory usage (but do NOT + * nuke image_data!) */ + + readpng_cleanup(FALSE); + fclose(infile); + + if (!image_data) { + fprintf(stderr, PROGNAME ": unable to decode PNG image\n"); + exit(3); + } + + + /* display image (composite with background if requested) */ + + Trace((stderr, "calling rpng_x_display_image()\n")) + if (rpng_x_display_image()) { + free(image_data); + exit(4); + } + Trace((stderr, "done with rpng_x_display_image()\n")) + + + /* wait for the user to tell us when to quit */ + + printf( + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); + fflush(stdout); + + do + XNextEvent(display, &e); + while (!(e.type == ButtonPress && e.xbutton.button == Button1) && + !(e.type == KeyPress && /* v--- or 1 for shifted keys */ + ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) )); + + + /* OK, we're done: clean up all image and X resources and go away */ + + rpng_x_cleanup(); + + return 0; +} + + + + + +static int rpng_x_create_window(void) +{ + uch *xdata; + int need_colormap = FALSE; + int screen, pad; + ulg bg_pixel = 0L; + ulg attrmask; + Window root; + XEvent e; + XGCValues gcvalues; + XSetWindowAttributes attr; + XTextProperty windowName, *pWindowName = &windowName; + XTextProperty iconName, *pIconName = &iconName; + XVisualInfo visual_info; + XSizeHints *size_hints; + XWMHints *wm_hints; + XClassHint *class_hints; + + + screen = DefaultScreen(display); + depth = DisplayPlanes(display, screen); + root = RootWindow(display, screen); + +#ifdef DEBUG + XSynchronize(display, True); +#endif + +#if 0 +/* GRR: add 8-bit support */ + if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) { + fprintf(stderr, + "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n", + depth); + return 2; + } + + XMatchVisualInfo(display, screen, depth, + (depth == 8)? PseudoColor : TrueColor, &visual_info); + visual = visual_info.visual; +#else + if (depth != 16 && depth != 24 && depth != 32) { + int visuals_matched = 0; + + Trace((stderr, "default depth is %d: checking other visuals\n", + depth)) + + /* 24-bit first */ + visual_info.screen = screen; + visual_info.depth = 24; + visual_list = XGetVisualInfo(display, + VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched); + if (visuals_matched == 0) { +/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */ + fprintf(stderr, "default screen depth %d not supported, and no" + " 24-bit visuals found\n", depth); + return 2; + } + Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n", + visuals_matched)) + visual = visual_list[0].visual; + depth = visual_list[0].depth; +/* + colormap_size = visual_list[0].colormap_size; + visual_class = visual->class; + visualID = XVisualIDFromVisual(visual); + */ + have_nondefault_visual = TRUE; + need_colormap = TRUE; + } else { + XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info); + visual = visual_info.visual; + } +#endif + + RMask = visual->red_mask; + GMask = visual->green_mask; + BMask = visual->blue_mask; + +/* GRR: add/check 8-bit support */ + if (depth == 8 || need_colormap) { + colormap = XCreateColormap(display, root, visual, AllocNone); + if (!colormap) { + fprintf(stderr, "XCreateColormap() failed\n"); + return 2; + } + have_colormap = TRUE; + } + if (depth == 15 || depth == 16) { + RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */ + GShift = 15 - rpng_x_msb(GMask); + BShift = 15 - rpng_x_msb(BMask); + } else if (depth > 16) { +#define NO_24BIT_MASKS +#ifdef NO_24BIT_MASKS + RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */ + GShift = rpng_x_msb(GMask) - 7; + BShift = rpng_x_msb(BMask) - 7; +#else + RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */ + GShift = 7 - rpng_x_msb(GMask); + BShift = 7 - rpng_x_msb(BMask); +#endif + } + if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) { + fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n"); + return 2; + } + +/*--------------------------------------------------------------------------- + Finally, create the window. + ---------------------------------------------------------------------------*/ + + attr.backing_store = Always; + attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask; + attrmask = CWBackingStore | CWEventMask; + if (have_nondefault_visual) { + attr.colormap = colormap; + attr.background_pixel = 0; + attr.border_pixel = 1; + attrmask |= CWColormap | CWBackPixel | CWBorderPixel; + } + + window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0, + depth, InputOutput, visual, attrmask, &attr); + + if (window == None) { + fprintf(stderr, "XCreateWindow() failed\n"); + return 2; + } else + have_window = TRUE; + + if (depth == 8) + XSetWindowColormap(display, window, colormap); + + if (!XStringListToTextProperty(&window_name, 1, pWindowName)) + pWindowName = NULL; + if (!XStringListToTextProperty(&icon_name, 1, pIconName)) + pIconName = NULL; + + /* OK if any hints allocation fails; XSetWMProperties() allows NULLs */ + + if ((size_hints = XAllocSizeHints()) != NULL) { + /* window will not be resizable */ + size_hints->flags = PMinSize | PMaxSize; + size_hints->min_width = size_hints->max_width = (int)image_width; + size_hints->min_height = size_hints->max_height = (int)image_height; + } + + if ((wm_hints = XAllocWMHints()) != NULL) { + wm_hints->initial_state = NormalState; + wm_hints->input = True; + /* wm_hints->icon_pixmap = icon_pixmap; */ + wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ; + } + + if ((class_hints = XAllocClassHint()) != NULL) { + class_hints->res_name = res_name; + class_hints->res_class = res_class; + } + + XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0, + size_hints, wm_hints, class_hints); + + /* various properties and hints no longer needed; free memory */ + if (pWindowName) + XFree(pWindowName->value); + if (pIconName) + XFree(pIconName->value); + if (size_hints) + XFree(size_hints); + if (wm_hints) + XFree(wm_hints); + if (class_hints) + XFree(class_hints); + + XMapWindow(display, window); + + gc = XCreateGC(display, window, 0, &gcvalues); + have_gc = TRUE; + +/*--------------------------------------------------------------------------- + Fill window with the specified background color. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + bg_pixel = ((ulg)bg_red << RShift) | + ((ulg)bg_green << GShift) | + ((ulg)bg_blue << BShift); + } else if (depth == 16) { + bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) | + ((((ulg)bg_green << 8) >> GShift) & GMask) | + ((((ulg)bg_blue << 8) >> BShift) & BMask); + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + XSetForeground(display, gc, bg_pixel); + XFillRectangle(display, window, gc, 0, 0, image_width, image_height); + +/*--------------------------------------------------------------------------- + Wait for first Expose event to do any drawing, then flush. + ---------------------------------------------------------------------------*/ + + do + XNextEvent(display, &e); + while (e.type != Expose || e.xexpose.count); + + XFlush(display); + +/*--------------------------------------------------------------------------- + Allocate memory for the X- and display-specific version of the image. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + xdata = (uch *)malloc(4*image_width*image_height); + pad = 32; + } else if (depth == 16) { + xdata = (uch *)malloc(2*image_width*image_height); + pad = 16; + } else /* depth == 8 */ { + xdata = (uch *)malloc(image_width*image_height); + pad = 8; + } + + if (!xdata) { + fprintf(stderr, PROGNAME ": unable to allocate image memory\n"); + return 4; + } + + ximage = XCreateImage(display, visual, depth, ZPixmap, 0, + (char *)xdata, image_width, image_height, pad, 0); + + if (!ximage) { + fprintf(stderr, PROGNAME ": XCreateImage() failed\n"); + free(xdata); + return 3; + } + + /* to avoid testing the byte order every pixel (or doubling the size of + * the drawing routine with a giant if-test), we arbitrarily set the byte + * order to MSBFirst and let Xlib worry about inverting things on little- + * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most + * efficient approach (the giant if-test would be better), but in the + * interest of clarity, we take the easy way out... */ + + ximage->byte_order = MSBFirst; + + return 0; + +} /* end function rpng_x_create_window() */ + + + + + +static int rpng_x_display_image(void) +{ + uch *src; + char *dest; + uch r, g, b, a; + ulg i, row, lastrow = 0; + ulg pixel; + int ximage_rowbytes = ximage->bytes_per_line; +/* int bpp = ximage->bits_per_pixel; */ + + + Trace((stderr, "beginning display loop (image_channels == %d)\n", + image_channels)) + Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n", + image_width, image_rowbytes, ximage_rowbytes)) + Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel)) + Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst? + "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown"))) + + if (depth == 24 || depth == 32) { + ulg red, green, blue; + + for (lastrow = row = 0; row < image_height; ++row) { + src = image_data + row*image_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (image_channels == 3) { + for (i = image_width; i > 0; --i) { + red = *src++; + green = *src++; + blue = *src++; +#ifdef NO_24BIT_MASKS + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + /* GRR BUG: this assumes bpp == 32, but may be 24: */ + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); +#else + red = (RShift < 0)? red << (-RShift) : red >> RShift; + green = (GShift < 0)? green << (-GShift) : green >> GShift; + blue = (BShift < 0)? blue << (-BShift) : blue >> BShift; + pixel = (red & RMask) | (green & GMask) | (blue & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); +#endif + } + } else /* if (image_channels == 4) */ { + for (i = image_width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (a == 255) { + red = r; + green = g; + blue = b; + } else if (a == 0) { + red = bg_red; + green = bg_green; + blue = bg_blue; + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result into the + * first argument */ + alpha_composite(red, r, a, bg_red); + alpha_composite(green, g, a, bg_green); + alpha_composite(blue, b, a, bg_blue); + } + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, image_width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else if (depth == 16) { + ush red, green, blue; + + for (lastrow = row = 0; row < image_height; ++row) { + src = image_data + row*image_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (image_channels == 3) { + for (i = image_width; i > 0; --i) { + red = ((ush)(*src) << 8); + ++src; + green = ((ush)(*src) << 8); + ++src; + blue = ((ush)(*src) << 8); + ++src; + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } else /* if (image_channels == 4) */ { + for (i = image_width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (a == 255) { + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } else if (a == 0) { + red = ((ush)bg_red << 8); + green = ((ush)bg_green << 8); + blue = ((ush)bg_blue << 8); + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result back into + * the first argument (== fg byte here: safe) */ + alpha_composite(r, r, a, bg_red); + alpha_composite(g, g, a, bg_green); + alpha_composite(b, b, a, bg_blue); + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, image_width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + Trace((stderr, "calling final XPutImage()\n")) + if (lastrow < image_height) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, image_width, image_height-lastrow); + XFlush(display); + } + + return 0; +} + + + + +static void rpng_x_cleanup(void) +{ + if (image_data) { + free(image_data); + image_data = NULL; + } + + if (ximage) { + if (ximage->data) { + free(ximage->data); /* we allocated it, so we free it */ + ximage->data = (char *)NULL; /* instead of XDestroyImage() */ + } + XDestroyImage(ximage); + ximage = NULL; + } + + if (have_gc) + XFreeGC(display, gc); + + if (have_window) + XDestroyWindow(display, window); + + if (have_colormap) + XFreeColormap(display, colormap); + + if (have_nondefault_visual) + XFree(visual_list); +} + + + + + +static int rpng_x_msb(ulg u32val) +{ + int i; + + for (i = 31; i >= 0; --i) { + if (u32val & 0x80000000L) + break; + u32val <<= 1; + } + return i; +} diff --git a/extern/libpng/include/contrib/gregbook/rpng2-win.c b/extern/libpng/include/contrib/gregbook/rpng2-win.c new file mode 100644 index 0000000000..fbdacb59bc --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/rpng2-win.c @@ -0,0 +1,1253 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program rpng2-win.c + + This program decodes and displays PNG files progressively, as if it were + a web browser (though the front end is only set up to read from files). + It supports gamma correction, user-specified background colors, and user- + specified background patterns (for transparent images). This version is + for 32-bit Windows; it may compile under 16-bit Windows with a little + tweaking (or maybe not). Thanks to Adam Costello and Pieter S. van der + Meulen for the "diamond" and "radial waves" patterns, respectively. + + to do (someday, maybe): + - handle quoted command-line args (especially filenames with spaces) + - finish resizable checkerboard-gradient (sizes 4-128?) + - use %.1023s to simplify truncation of title-bar string? + - have minimum window width: oh well + + --------------------------------------------------------------------------- + + Changelog: + - 1.01: initial public release + - 1.02: fixed cut-and-paste error in usage screen (oops...) + - 1.03: modified to allow abbreviated options + - 1.04: removed bogus extra argument from usage fprintf() [Glenn R-P?]; + fixed command-line parsing bug + - 1.10: enabled "message window"/console (thanks to David Geldreich) + - 1.20: added runtime MMX-enabling/disabling and new -mmx* options + - 1.21: made minor tweak to usage screen to fit within 25-line console + - 1.22: added AMD64/EM64T support (__x86_64__) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed 64-bit typo in readpng2.c + - 2.02: fixed improper display of usage screen on PNG error(s); fixed + unexpected-EOF and file-read-error cases + - 2.03: removed runtime MMX-enabling/disabling and obsolete -mmx* options + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng2-win" +#define LONGNAME "Progressive PNG Viewer for Windows" +#define VERSION "2.02 of 16 March 2008" + +#include +#include +#include +#include /* for jmpbuf declaration in readpng2.h */ +#include +#include /* only for PvdM background code */ +#include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else +#include /* only for _getch() */ +#endif + +/* all for PvdM background code: */ +#ifndef PI +# define PI 3.141592653589793238 +#endif +#define PI_2 (PI*0.5) +#define INV_PI_360 (360.0 / PI) +#define MAX(a,b) (a>b?a:b) +#define MIN(a,b) (a> 8)) >> 8); \ +} + + +#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this + * block size corresponds roughly to a download + * speed 10% faster than theoretical 33.6K maximum + * (assuming 8 data bits, 1 stop bit and no other + * overhead) */ + +/* local prototypes */ +static void rpng2_win_init(void); +static int rpng2_win_create_window(void); +static int rpng2_win_load_bg_image(void); +static void rpng2_win_display_row(ulg row); +static void rpng2_win_finish_display(void); +static void rpng2_win_cleanup(void); +LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM); + + +static char titlebar[1024]; +static char *progname = PROGNAME; +static char *appname = LONGNAME; +static char *filename; +static FILE *infile; + +static mainprog_info rpng2_info; + +static uch inbuf[INBUFSIZE]; +static int incount; + +static int pat = 6; /* must be less than num_bgpat */ +static int bg_image = 0; +static int bgscale = 16; +static ulg bg_rowbytes; +static uch *bg_data; + +static struct rgb_color { + uch r, g, b; +} rgb[] = { + { 0, 0, 0}, /* 0: black */ + {255, 255, 255}, /* 1: white */ + {173, 132, 57}, /* 2: tan */ + { 64, 132, 0}, /* 3: medium green */ + {189, 117, 1}, /* 4: gold */ + {253, 249, 1}, /* 5: yellow */ + { 0, 0, 255}, /* 6: blue */ + { 0, 0, 120}, /* 7: medium blue */ + {255, 0, 255}, /* 8: magenta */ + { 64, 0, 64}, /* 9: dark magenta */ + {255, 0, 0}, /* 10: red */ + { 64, 0, 0}, /* 11: dark red */ + {255, 127, 0}, /* 12: orange */ + {192, 96, 0}, /* 13: darker orange */ + { 24, 60, 0}, /* 14: dark green-yellow */ + { 85, 125, 200} /* 15: ice blue */ +}; +/* not used for now, but should be for error-checking: +static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color); + */ + +/* + This whole struct is a fairly cheesy way to keep the number of + command-line options to a minimum. The radial-waves background + type is a particularly poor fit to the integer elements of the + struct...but a few macros and a little fixed-point math will do + wonders for ya. + + type bits: + F E D C B A 9 8 7 6 5 4 3 2 1 0 + | | | | | + | | +-+-+-- 0 = sharp-edged checkerboard + | | 1 = soft diamonds + | | 2 = radial waves + | | 3-7 = undefined + | +-- gradient #2 inverted? + +-- alternating columns inverted? + */ +static struct background_pattern { + ush type; + int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */ + int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/ +} bg[] = { + {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */ + {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */ + {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */ + {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */ + {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */ + {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */ + {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */ + {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */ + {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */ + {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */ + {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */ + {1, 3,0, 0,0}, /* diamonds: medium green vs. black */ + {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */ + {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */ + {2, 16, 256, 100, 250}, /* radial: very tight spiral */ + {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */ +}; +static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern); + + +/* Windows-specific global variables (could go in struct, but messy...) */ +static ulg wimage_rowbytes; +static uch *dib; +static uch *wimage_data; +static BITMAPINFOHEADER *bmih; + +static HWND global_hwnd; +static HINSTANCE global_hInst; +static int global_showmode; + + + + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) +{ + char *args[1024]; /* arbitrary limit, but should suffice */ + char **argv = args; + char *p, *q, *bgstr = NULL; + int argc = 0; + int rc, alen, flen; + int error = 0; + int timing = FALSE; + int have_bg = FALSE; + double LUT_exponent; /* just the lookup table */ + double CRT_exponent = 2.2; /* just the monitor */ + double default_display_exponent; /* whole display system */ + MSG msg; + + + /* First initialize a few things, just to be sure--memset takes care of + * default background color (black), booleans (FALSE), pointers (NULL), + * etc. */ + + global_hInst = hInst; + global_showmode = showmode; + filename = (char *)NULL; + memset(&rpng2_info, 0, sizeof(mainprog_info)); + +#ifndef __CYGWIN__ + /* Next reenable console output, which normally goes to the bit bucket + * for windowed apps. Closing the console window will terminate the + * app. Thanks to David.Geldreich@realviz.com for supplying the magical + * incantation. */ + + AllocConsole(); + freopen("CONOUT$", "a", stderr); + freopen("CONOUT$", "a", stdout); +#endif + + /* Set the default value for our display-system exponent, i.e., the + * product of the CRT exponent and the exponent corresponding to + * the frame-buffer's lookup table (LUT), if any. This is not an + * exhaustive list of LUT values (e.g., OpenStep has a lot of weird + * ones), but it should cover 99% of the current possibilities. And + * yes, these ifdefs are completely wasted in a Windows program... */ + +#if defined(NeXT) + /* third-party utilities can modify the default LUT exponent */ + LUT_exponent = 1.0 / 2.2; + /* + if (some_next_function_that_returns_gamma(&next_gamma)) + LUT_exponent = 1.0 / next_gamma; + */ +#elif defined(sgi) + LUT_exponent = 1.0 / 1.7; + /* there doesn't seem to be any documented function to + * get the "gamma" value, so we do it the hard way */ + infile = fopen("/etc/config/system.glGammaVal", "r"); + if (infile) { + double sgi_gamma; + + fgets(tmpline, 80, infile); + fclose(infile); + sgi_gamma = atof(tmpline); + if (sgi_gamma > 0.0) + LUT_exponent = 1.0 / sgi_gamma; + } +#elif defined(Macintosh) + LUT_exponent = 1.8 / 2.61; + /* + if (some_mac_function_that_returns_gamma(&mac_gamma)) + LUT_exponent = mac_gamma / 2.61; + */ +#else + LUT_exponent = 1.0; /* assume no LUT: most PCs */ +#endif + + /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ + default_display_exponent = LUT_exponent * CRT_exponent; + + + /* If the user has set the SCREEN_GAMMA environment variable as suggested + * (somewhat imprecisely) in the libpng documentation, use that; otherwise + * use the default value we just calculated. Either way, the user may + * override this via a command-line option. */ + + if ((p = getenv("SCREEN_GAMMA")) != NULL) + rpng2_info.display_exponent = atof(p); + else + rpng2_info.display_exponent = default_display_exponent; + + + /* Windows really hates command lines, so we have to set up our own argv. + * Note that we do NOT bother with quoted arguments here, so don't use + * filenames with spaces in 'em! */ + + argv[argc++] = PROGNAME; + p = cmd; + for (;;) { + if (*p == ' ') + while (*++p == ' ') + ; + /* now p points at the first non-space after some spaces */ + if (*p == '\0') + break; /* nothing after the spaces: done */ + argv[argc++] = q = p; + while (*q && *q != ' ') + ++q; + /* now q points at a space or the end of the string */ + if (*q == '\0') + break; /* last argv already terminated; quit */ + *q = '\0'; /* change space to terminator */ + p = q + 1; + } + argv[argc] = NULL; /* terminate the argv array itself */ + + + /* Now parse the command line for options and the PNG filename. */ + + while (*++argv && !error) { + if (!strncmp(*argv, "-gamma", 2)) { + if (!*++argv) + ++error; + else { + rpng2_info.display_exponent = atof(*argv); + if (rpng2_info.display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { + if (!*++argv) + ++error; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + have_bg = TRUE; + bg_image = FALSE; + } + } + } else if (!strncmp(*argv, "-bgpat", 4)) { + if (!*++argv) + ++error; + else { + pat = atoi(*argv) - 1; + if (pat < 0 || pat >= num_bgpat) + ++error; + else { + bg_image = TRUE; + have_bg = FALSE; + } + } + } else if (!strncmp(*argv, "-timing", 2)) { + timing = TRUE; + } else { + if (**argv != '-') { + filename = *argv; + if (argv[1]) /* shouldn't be any more args after filename */ + ++error; + } else + ++error; /* not expecting any other options */ + } + } + + if (!filename) + ++error; + + + /* print usage screen if any errors up to this point */ + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); + readpng2_version_info(); + fprintf(stderr, "\n" + "Usage: %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n" + " %*s file.png\n\n" + " exp \ttransfer-function exponent (``gamma'') of the display\n" + "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" + "\t\t to the product of the lookup-table exponent (varies)\n" + "\t\t and the CRT exponent (usually 2.2); must be positive\n" + " bg \tdesired background color in 7-character hex RGB format\n" + "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" + "\t\t used with transparent images; overrides -bgpat option\n" + " pat \tdesired background pattern number (1-%d); used with\n" + "\t\t transparent images; overrides -bgcolor option\n" + " -timing\tenables delay for every block read, to simulate modem\n" + "\t\t download of image (~36 Kbps)\n" + "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" +#ifndef __CYGWIN__ + "Press Q or Esc to quit this usage screen. ", +#else + , +#endif + PROGNAME, +#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \ + !(defined(__CYGWIN__) || defined(__MINGW32__)) + (int)strlen(PROGNAME), " ", +#endif + (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat); + fflush(stderr); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(1); + } + + + if (!(infile = fopen(filename, "rb"))) { + fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); + ++error; + } else { + incount = fread(inbuf, 1, INBUFSIZE, infile); + if (incount < 8 || !readpng2_check_sig(inbuf, 8)) { + fprintf(stderr, PROGNAME + ": [%s] is not a PNG file: incorrect signature\n", + filename); + ++error; + } else if ((rc = readpng2_init(&rpng2_info)) != 0) { + switch (rc) { + case 2: + fprintf(stderr, PROGNAME + ": [%s] has bad IHDR (libpng longjmp)\n", filename); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown readpng2_init() error\n"); + break; + } + ++error; + } + if (error) + fclose(infile); + } + + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(2); + } else { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ + fprintf(stderr, + "\n [console window: closing this window will terminate %s]\n\n", + PROGNAME); +#endif + fflush(stderr); + } + + + /* set the title-bar string, but make sure buffer doesn't overflow */ + + alen = strlen(appname); + flen = strlen(filename); + if (alen + flen + 3 > 1023) + sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); + else + sprintf(titlebar, "%s: %s", appname, filename); + + + /* set some final rpng2_info variables before entering main data loop */ + + if (have_bg) { + unsigned r, g, b; /* this approach quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + rpng2_info.bg_red = (uch)r; + rpng2_info.bg_green = (uch)g; + rpng2_info.bg_blue = (uch)b; + } else + rpng2_info.need_bgcolor = TRUE; + + rpng2_info.state = kPreInit; + rpng2_info.mainprog_init = rpng2_win_init; + rpng2_info.mainprog_display_row = rpng2_win_display_row; + rpng2_info.mainprog_finish_display = rpng2_win_finish_display; + + + /* OK, this is the fun part: call readpng2_decode_data() at the start of + * the loop to deal with our first buffer of data (read in above to verify + * that the file is a PNG image), then loop through the file and continue + * calling the same routine to handle each chunk of data. It in turn + * passes the data to libpng, which will invoke one or more of our call- + * backs as decoded data become available. We optionally call Sleep() for + * one second per iteration to simulate downloading the image via an analog + * modem. */ + + for (;;) { + Trace((stderr, "about to call readpng2_decode_data()\n")) + if (readpng2_decode_data(&rpng2_info, inbuf, incount)) + ++error; + Trace((stderr, "done with readpng2_decode_data()\n")) + + if (error || incount != INBUFSIZE || rpng2_info.state == kDone) { + if (rpng2_info.state == kDone) { + Trace((stderr, "done decoding PNG image\n")) + } else if (ferror(infile)) { + fprintf(stderr, PROGNAME + ": error while reading PNG image file\n"); + exit(3); + } else if (feof(infile)) { + fprintf(stderr, PROGNAME ": end of file reached " + "(unexpectedly) while reading PNG image file\n"); + exit(3); + } else /* if (error) */ { + // will print error message below + } + break; + } + + if (timing) + Sleep(1000L); + + incount = fread(inbuf, 1, INBUFSIZE, infile); + } + + + /* clean up PNG stuff and report any decoding errors */ + + fclose(infile); + Trace((stderr, "about to call readpng2_cleanup()\n")) + readpng2_cleanup(&rpng2_info); + + if (error) { + fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n"); + exit(3); + } + + + /* wait for the user to tell us when to quit */ + + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + + /* we're done: clean up all image and Windows resources and go away */ + + Trace((stderr, "about to call rpng2_win_cleanup()\n")) + rpng2_win_cleanup(); + + return msg.wParam; +} + + + + + +/* this function is called by readpng2_info_callback() in readpng2.c, which + * in turn is called by libpng after all of the pre-IDAT chunks have been + * read and processed--i.e., we now have enough info to finish initializing */ + +static void rpng2_win_init() +{ + ulg i; + ulg rowbytes = rpng2_info.rowbytes; + + Trace((stderr, "beginning rpng2_win_init()\n")) + Trace((stderr, " rowbytes = %d\n", rpng2_info.rowbytes)) + Trace((stderr, " width = %ld\n", rpng2_info.width)) + Trace((stderr, " height = %ld\n", rpng2_info.height)) + + rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height); + if (!rpng2_info.image_data) { + readpng2_cleanup(&rpng2_info); + return; + } + + rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *)); + if (!rpng2_info.row_pointers) { + free(rpng2_info.image_data); + rpng2_info.image_data = NULL; + readpng2_cleanup(&rpng2_info); + return; + } + + for (i = 0; i < rpng2_info.height; ++i) + rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes; + +/*--------------------------------------------------------------------------- + Do the basic Windows initialization stuff, make the window, and fill it + with the user-specified, file-specified or default background color. + ---------------------------------------------------------------------------*/ + + if (rpng2_win_create_window()) { + readpng2_cleanup(&rpng2_info); + return; + } + + rpng2_info.state = kWindowInit; +} + + + + + +static int rpng2_win_create_window() +{ + uch bg_red = rpng2_info.bg_red; + uch bg_green = rpng2_info.bg_green; + uch bg_blue = rpng2_info.bg_blue; + uch *dest; + int extra_width, extra_height; + ulg i, j; + WNDCLASSEX wndclass; + RECT rect; + + +/*--------------------------------------------------------------------------- + Allocate memory for the display-specific version of the image (round up + to multiple of 4 for Windows DIB). + ---------------------------------------------------------------------------*/ + + wimage_rowbytes = ((3*rpng2_info.width + 3L) >> 2) << 2; + + if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + + wimage_rowbytes*rpng2_info.height))) + { + return 4; /* fail */ + } + +/*--------------------------------------------------------------------------- + Initialize the DIB. Negative height means to use top-down BMP ordering + (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8 + implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values + directly => wimage_data begins immediately after BMP header. + ---------------------------------------------------------------------------*/ + + memset(dib, 0, sizeof(BITMAPINFOHEADER)); + bmih = (BITMAPINFOHEADER *)dib; + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = rpng2_info.width; + bmih->biHeight = -((long)rpng2_info.height); + bmih->biPlanes = 1; + bmih->biBitCount = 24; + bmih->biCompression = 0; + wimage_data = dib + sizeof(BITMAPINFOHEADER); + +/*--------------------------------------------------------------------------- + Fill window with the specified background color (default is black), but + defer loading faked "background image" until window is displayed (may be + slow to compute). Data are in BGR order. + ---------------------------------------------------------------------------*/ + + if (bg_image) { /* just fill with black for now */ + memset(wimage_data, 0, wimage_rowbytes*rpng2_info.height); + } else { + for (j = 0; j < rpng2_info.height; ++j) { + dest = wimage_data + j*wimage_rowbytes; + for (i = rpng2_info.width; i > 0; --i) { + *dest++ = bg_blue; + *dest++ = bg_green; + *dest++ = bg_red; + } + } + } + +/*--------------------------------------------------------------------------- + Set the window parameters. + ---------------------------------------------------------------------------*/ + + memset(&wndclass, 0, sizeof(wndclass)); + + wndclass.cbSize = sizeof(wndclass); + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = rpng2_win_wndproc; + wndclass.hInstance = global_hInst; + wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = progname; + wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + RegisterClassEx(&wndclass); + +/*--------------------------------------------------------------------------- + Finally, create the window. + ---------------------------------------------------------------------------*/ + + extra_width = 2*(GetSystemMetrics(SM_CXBORDER) + + GetSystemMetrics(SM_CXDLGFRAME)); + extra_height = 2*(GetSystemMetrics(SM_CYBORDER) + + GetSystemMetrics(SM_CYDLGFRAME)) + + GetSystemMetrics(SM_CYCAPTION); + + global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, rpng2_info.width+extra_width, + rpng2_info.height+extra_height, NULL, NULL, global_hInst, NULL); + + ShowWindow(global_hwnd, global_showmode); + UpdateWindow(global_hwnd); + +/*--------------------------------------------------------------------------- + Now compute the background image and display it. If it fails (memory + allocation), revert to a plain background color. + ---------------------------------------------------------------------------*/ + + if (bg_image) { + static const char *msg = "Computing background image..."; + int x, y, len = strlen(msg); + HDC hdc = GetDC(global_hwnd); + TEXTMETRIC tm; + + GetTextMetrics(hdc, &tm); + x = (rpng2_info.width - len*tm.tmAveCharWidth)/2; + y = (rpng2_info.height - tm.tmHeight)/2; + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + /* this can still begin out of bounds even if x is positive (???): */ + TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len); + ReleaseDC(global_hwnd, hdc); + + rpng2_win_load_bg_image(); /* resets bg_image if fails */ + } + + if (!bg_image) { + for (j = 0; j < rpng2_info.height; ++j) { + dest = wimage_data + j*wimage_rowbytes; + for (i = rpng2_info.width; i > 0; --i) { + *dest++ = bg_blue; + *dest++ = bg_green; + *dest++ = bg_red; + } + } + } + + rect.left = 0L; + rect.top = 0L; + rect.right = (LONG)rpng2_info.width; /* possibly off by one? */ + rect.bottom = (LONG)rpng2_info.height; /* possibly off by one? */ + InvalidateRect(global_hwnd, &rect, FALSE); + UpdateWindow(global_hwnd); /* similar to XFlush() */ + + return 0; + +} /* end function rpng2_win_create_window() */ + + + + + +static int rpng2_win_load_bg_image() +{ + uch *src, *dest; + uch r1, r2, g1, g2, b1, b2; + uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv; + int k, hmax, max; + int xidx, yidx, yidx_max = (bgscale-1); + int even_odd_vert, even_odd_horiz, even_odd; + int invert_gradient2 = (bg[pat].type & 0x08); + int invert_column; + ulg i, row; + +/*--------------------------------------------------------------------------- + Allocate buffer for fake background image to be used with transparent + images; if this fails, revert to plain background color. + ---------------------------------------------------------------------------*/ + + bg_rowbytes = 3 * rpng2_info.width; + bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height); + if (!bg_data) { + fprintf(stderr, PROGNAME + ": unable to allocate memory for background image\n"); + bg_image = 0; + return 1; + } + +/*--------------------------------------------------------------------------- + Vertical gradients (ramps) in NxN squares, alternating direction and + colors (N == bgscale). + ---------------------------------------------------------------------------*/ + + if ((bg[pat].type & 0x07) == 0) { + uch r1_min = rgb[bg[pat].rgb1_min].r; + uch g1_min = rgb[bg[pat].rgb1_min].g; + uch b1_min = rgb[bg[pat].rgb1_min].b; + uch r2_min = rgb[bg[pat].rgb2_min].r; + uch g2_min = rgb[bg[pat].rgb2_min].g; + uch b2_min = rgb[bg[pat].rgb2_min].b; + int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min; + int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min; + int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min; + int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min; + int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min; + int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = row % bgscale; + even_odd_vert = (row / bgscale) & 1; + + r1 = r1_min + (r1_diff * yidx) / yidx_max; + g1 = g1_min + (g1_diff * yidx) / yidx_max; + b1 = b1_min + (b1_diff * yidx) / yidx_max; + r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max; + g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max; + b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max; + + r2 = r2_min + (r2_diff * yidx) / yidx_max; + g2 = g2_min + (g2_diff * yidx) / yidx_max; + b2 = b2_min + (b2_diff * yidx) / yidx_max; + r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max; + g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max; + b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max; + + dest = bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + even_odd_horiz = (i / bgscale) & 1; + even_odd = even_odd_vert ^ even_odd_horiz; + invert_column = + (even_odd_horiz && (bg[pat].type & 0x10)); + if (even_odd == 0) { /* gradient #1 */ + if (invert_column) { + *dest++ = r1_inv; + *dest++ = g1_inv; + *dest++ = b1_inv; + } else { + *dest++ = r1; + *dest++ = g1; + *dest++ = b1; + } + } else { /* gradient #2 */ + if ((invert_column && invert_gradient2) || + (!invert_column && !invert_gradient2)) + { + *dest++ = r2; /* not inverted or */ + *dest++ = g2; /* doubly inverted */ + *dest++ = b2; + } else { + *dest++ = r2_inv; + *dest++ = g2_inv; /* singly inverted */ + *dest++ = b2_inv; + } + } + } + } + +/*--------------------------------------------------------------------------- + Soft gradient-diamonds with scale = bgscale. Code contributed by Adam + M. Costello. + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 1) { + + hmax = (bgscale-1)/2; /* half the max weight of a color */ + max = 2*hmax; /* the max weight of a color */ + + r1 = rgb[bg[pat].rgb1_max].r; + g1 = rgb[bg[pat].rgb1_max].g; + b1 = rgb[bg[pat].rgb1_max].b; + r2 = rgb[bg[pat].rgb2_max].r; + g2 = rgb[bg[pat].rgb2_max].g; + b2 = rgb[bg[pat].rgb2_max].b; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = row % bgscale; + if (yidx > hmax) + yidx = bgscale-1 - yidx; + dest = bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + xidx = i % bgscale; + if (xidx > hmax) + xidx = bgscale-1 - xidx; + k = xidx + yidx; + *dest++ = (k*r1 + (max-k)*r2) / max; + *dest++ = (k*g1 + (max-k)*g2) / max; + *dest++ = (k*b1 + (max-k)*b2) / max; + } + } + +/*--------------------------------------------------------------------------- + Radial "starburst" with azimuthal sinusoids; [eventually number of sinu- + soids will equal bgscale?]. This one is slow but very cool. Code con- + tributed by Pieter S. van der Meulen (originally in Smalltalk). + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 2) { + uch ch; + int ii, x, y, hw, hh, grayspot; + double freq, rotate, saturate, gray, intensity; + double angle=0.0, aoffset=0.0, maxDist, dist; + double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t; + + fprintf(stderr, "%s: computing radial background...", + PROGNAME); + fflush(stderr); + + hh = rpng2_info.height / 2; + hw = rpng2_info.width / 2; + + /* variables for radial waves: + * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED] + * freq: number of color beams originating from the center + * grayspot: size of the graying center area (anti-alias) + * rotate: rotation of the beams as a function of radius + * saturate: saturation of beams' shape azimuthally + */ + angle = CLIP(angle, 0.0, 360.0); + grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw)); + freq = MAX((double)bg[pat].bg_freq, 0.0); + saturate = (double)bg[pat].bg_bsat * 0.1; + rotate = (double)bg[pat].bg_brot * 0.1; + gray = 0.0; + intensity = 0.0; + maxDist = (double)((hw*hw) + (hh*hh)); + + for (row = 0; row < rpng2_info.height; ++row) { + y = row - hh; + dest = bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + x = i - hw; + angle = (x == 0)? PI_2 : atan((double)y / (double)x); + gray = (double)MAX(ABS(y), ABS(x)) / grayspot; + gray = MIN(1.0, gray); + dist = (double)((x*x) + (y*y)) / maxDist; + intensity = cos((angle+(rotate*dist*PI)) * freq) * + gray * saturate; + intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5; + hue = (angle + PI) * INV_PI_360 + aoffset; + s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh)); + s = MIN(MAX(s,0.0), 1.0); + v = MIN(MAX(intensity,0.0), 1.0); + + if (s == 0.0) { + ch = (uch)(v * 255.0); + *dest++ = ch; + *dest++ = ch; + *dest++ = ch; + } else { + if ((hue < 0.0) || (hue >= 360.0)) + hue -= (((int)(hue / 360.0)) * 360.0); + hue /= 60.0; + ii = (int)hue; + f = hue - (double)ii; + p = (1.0 - s) * v; + q = (1.0 - (s * f)) * v; + t = (1.0 - (s * (1.0 - f))) * v; + if (ii == 0) { red = v; green = t; blue = p; } + else if (ii == 1) { red = q; green = v; blue = p; } + else if (ii == 2) { red = p; green = v; blue = t; } + else if (ii == 3) { red = p; green = q; blue = v; } + else if (ii == 4) { red = t; green = p; blue = v; } + else if (ii == 5) { red = v; green = p; blue = q; } + *dest++ = (uch)(red * 255.0); + *dest++ = (uch)(green * 255.0); + *dest++ = (uch)(blue * 255.0); + } + } + } + fprintf(stderr, "done.\n"); + fflush(stderr); + } + +/*--------------------------------------------------------------------------- + Blast background image to display buffer before beginning PNG decode; + calling function will handle invalidation and UpdateWindow() call. + ---------------------------------------------------------------------------*/ + + for (row = 0; row < rpng2_info.height; ++row) { + src = bg_data + row*bg_rowbytes; + dest = wimage_data + row*wimage_rowbytes; + for (i = rpng2_info.width; i > 0; --i) { + r1 = *src++; + g1 = *src++; + b1 = *src++; + *dest++ = b1; + *dest++ = g1; /* note reverse order */ + *dest++ = r1; + } + } + + return 0; + +} /* end function rpng2_win_load_bg_image() */ + + + + + +static void rpng2_win_display_row(ulg row) +{ + uch bg_red = rpng2_info.bg_red; + uch bg_green = rpng2_info.bg_green; + uch bg_blue = rpng2_info.bg_blue; + uch *src, *src2=NULL, *dest; + uch r, g, b, a; + ulg i; + static int rows=0; + static ulg firstrow; + +/*--------------------------------------------------------------------------- + rows and firstrow simply track how many rows (and which ones) have not + yet been displayed; alternatively, we could call InvalidateRect() for + every row and not bother with the records-keeping. + ---------------------------------------------------------------------------*/ + + Trace((stderr, "beginning rpng2_win_display_row()\n")) + + if (rows == 0) + firstrow = row; /* first row not yet displayed */ + + ++rows; /* count of rows received but not yet displayed */ + +/*--------------------------------------------------------------------------- + Aside from the use of the rpng2_info struct and the lack of an outer + loop (over rows), this routine is identical to rpng_win_display_image() + in the non-progressive version of the program. + ---------------------------------------------------------------------------*/ + + src = rpng2_info.image_data + row*rpng2_info.rowbytes; + if (bg_image) + src2 = bg_data + row*bg_rowbytes; + dest = wimage_data + row*wimage_rowbytes; + + if (rpng2_info.channels == 3) { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + *dest++ = b; + *dest++ = g; /* note reverse order */ + *dest++ = r; + } + } else /* if (rpng2_info.channels == 4) */ { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (bg_image) { + bg_red = *src2++; + bg_green = *src2++; + bg_blue = *src2++; + } + if (a == 255) { + *dest++ = b; + *dest++ = g; + *dest++ = r; + } else if (a == 0) { + *dest++ = bg_blue; + *dest++ = bg_green; + *dest++ = bg_red; + } else { + /* this macro (copied from png.h) composites the + * foreground and background values and puts the + * result into the first argument; there are no + * side effects with the first argument */ + alpha_composite(*dest++, b, a, bg_blue); + alpha_composite(*dest++, g, a, bg_green); + alpha_composite(*dest++, r, a, bg_red); + } + } + } + +/*--------------------------------------------------------------------------- + Display after every 16 rows or when on last row. (Region may include + previously displayed lines due to interlacing--i.e., not contiguous.) + ---------------------------------------------------------------------------*/ + + if ((rows & 0xf) == 0 || row == rpng2_info.height-1) { + RECT rect; + + rect.left = 0L; + rect.top = (LONG)firstrow; + rect.right = (LONG)rpng2_info.width; /* possibly off by one? */ + rect.bottom = (LONG)row + 1L; /* possibly off by one? */ + InvalidateRect(global_hwnd, &rect, FALSE); + UpdateWindow(global_hwnd); /* similar to XFlush() */ + rows = 0; + } + +} /* end function rpng2_win_display_row() */ + + + + + +static void rpng2_win_finish_display() +{ + Trace((stderr, "beginning rpng2_win_finish_display()\n")) + + /* last row has already been displayed by rpng2_win_display_row(), so + * we have nothing to do here except set a flag and let the user know + * that the image is done */ + + rpng2_info.state = kDone; + printf( +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); + fflush(stdout); +} + + + + + +static void rpng2_win_cleanup() +{ + if (bg_image && bg_data) { + free(bg_data); + bg_data = NULL; + } + + if (rpng2_info.image_data) { + free(rpng2_info.image_data); + rpng2_info.image_data = NULL; + } + + if (rpng2_info.row_pointers) { + free(rpng2_info.row_pointers); + rpng2_info.row_pointers = NULL; + } + + if (dib) { + free(dib); + dib = NULL; + } +} + + + + + +LRESULT CALLBACK rpng2_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP) +{ + HDC hdc; + PAINTSTRUCT ps; + int rc; + + switch (iMsg) { + case WM_CREATE: + /* one-time processing here, if any */ + return 0; + + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + rc = StretchDIBits(hdc, 0, 0, rpng2_info.width, rpng2_info.height, + 0, 0, rpng2_info.width, rpng2_info.height, + wimage_data, (BITMAPINFO *)bmih, + 0, SRCCOPY); + EndPaint(hwnd, &ps); + return 0; + + /* wait for the user to tell us when to quit */ + case WM_CHAR: + switch (wP) { /* only need one, so ignore repeat count */ + case 'q': + case 'Q': + case 0x1B: /* Esc key */ + PostQuitMessage(0); + } + return 0; + + case WM_LBUTTONDOWN: /* another way of quitting */ + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hwnd, iMsg, wP, lP); +} diff --git a/extern/libpng/include/contrib/gregbook/rpng2-x.c b/extern/libpng/include/contrib/gregbook/rpng2-x.c new file mode 100644 index 0000000000..b04c5c6b69 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/rpng2-x.c @@ -0,0 +1,2107 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program rpng2-x.c + + This program decodes and displays PNG files progressively, as if it were + a web browser (though the front end is only set up to read from files). + It supports gamma correction, user-specified background colors, and user- + specified background patterns (for transparent images). This version is + for the X Window System (tested by the author under Unix and by Martin + Zinser under OpenVMS; may work under OS/2 with a little tweaking). + + Thanks to Adam Costello and Pieter S. van der Meulen for the "diamond" + and "radial waves" patterns, respectively. + + to do (someday, maybe): + - fix expose/redraw code: don't draw entire row if only part exposed + - 8-bit (colormapped) X support + - finish resizable checkerboard-gradient (sizes 4-128?) + - use %.1023s to simplify truncation of title-bar string? + + --------------------------------------------------------------------------- + + Changelog: + - 1.01: initial public release + - 1.02: modified to allow abbreviated options; fixed char/uchar mismatch + - 1.10: added support for non-default visuals; fixed X pixel-conversion + - 1.11: added -usleep option for demos; fixed command-line parsing bug + - 1.12: added -pause option for demos and testing + - 1.20: added runtime MMX-enabling/disabling and new -mmx* options + - 1.21: fixed some small X memory leaks (thanks to François Petitjean) + - 1.22: fixed XFreeGC() crash bug (thanks to Patrick Welche) + - 1.23: added -bgpat 0 mode (std white/gray checkerboard, 8x8 squares) + - 1.30: added -loop option for -bgpat (ifdef FEATURE_LOOP); fixed bpp = + 24; added support for X resources (thanks to Gerhard Niklasch) + - 1.31: added code to skip unused chunks (thanks to Glenn Randers-Pehrson) + - 1.32: added AMD64/EM64T support (__x86_64__); added basic expose/redraw + handling + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed 64-bit typo in readpng2.c; fixed -pause usage description + - 2.02: fixed improper display of usage screen on PNG error(s); fixed + unexpected-EOF and file-read-error cases; fixed Trace() cut-and- + paste bugs + - 2.03: deleted runtime MMX-enabling/disabling and obsolete -mmx* options + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng2-x" +#define LONGNAME "Progressive PNG Viewer for X" +#define VERSION "2.03 of 25 February 2010" +#define RESNAME "rpng2" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ + +#include +#include +#include +#include +#include /* for jmpbuf declaration in readpng2.h */ +#include +#include /* only for PvdM background code */ +#include +#include +#include +#include /* defines XK_* macros */ + +#ifdef VMS +# include +#endif + +/* all for PvdM background code: */ +#ifndef PI +# define PI 3.141592653589793238 +#endif +#define PI_2 (PI*0.5) +#define INV_PI_360 (360.0 / PI) +#define MAX(a,b) (a>b?a:b) +#define MIN(a,b) (a> 8)) >> 8); \ +} + + +#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this + * block size corresponds roughly to a download + * speed 10% faster than theoretical 33.6K maximum + * (assuming 8 data bits, 1 stop bit and no other + * overhead) */ + +/* local prototypes */ +static void rpng2_x_init (void); +static int rpng2_x_create_window (void); +static int rpng2_x_load_bg_image (void); +static void rpng2_x_display_row (ulg row); +static void rpng2_x_finish_display (void); +static void rpng2_x_redisplay_image (ulg startcol, ulg startrow, + ulg width, ulg height); +#ifdef FEATURE_LOOP +static void rpng2_x_reload_bg_image (void); +static int is_number (char *p); +#endif +static void rpng2_x_cleanup (void); +static int rpng2_x_msb (ulg u32val); + + +static char titlebar[1024], *window_name = titlebar; +static char *appname = LONGNAME; +static char *icon_name = PROGNAME; +static char *res_name = RESNAME; +static char *res_class = RESCLASS; +static char *filename; +static FILE *infile; + +static mainprog_info rpng2_info; + +static uch inbuf[INBUFSIZE]; +static int incount; + +static int pat = 6; /* must be less than num_bgpat */ +static int bg_image = 0; +static int bgscale, bgscale_default = 16; +static ulg bg_rowbytes; +static uch *bg_data; + +int pause_after_pass = FALSE; +int demo_timing = FALSE; +ulg usleep_duration = 0L; + +static struct rgb_color { + uch r, g, b; +} rgb[] = { + { 0, 0, 0}, /* 0: black */ + {255, 255, 255}, /* 1: white */ + {173, 132, 57}, /* 2: tan */ + { 64, 132, 0}, /* 3: medium green */ + {189, 117, 1}, /* 4: gold */ + {253, 249, 1}, /* 5: yellow */ + { 0, 0, 255}, /* 6: blue */ + { 0, 0, 120}, /* 7: medium blue */ + {255, 0, 255}, /* 8: magenta */ + { 64, 0, 64}, /* 9: dark magenta */ + {255, 0, 0}, /* 10: red */ + { 64, 0, 0}, /* 11: dark red */ + {255, 127, 0}, /* 12: orange */ + {192, 96, 0}, /* 13: darker orange */ + { 24, 60, 0}, /* 14: dark green-yellow */ + { 85, 125, 200}, /* 15: ice blue */ + {192, 192, 192} /* 16: Netscape/Mosaic gray */ +}; +/* not used for now, but should be for error-checking: +static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color); + */ + +/* + This whole struct is a fairly cheesy way to keep the number of + command-line options to a minimum. The radial-waves background + type is a particularly poor fit to the integer elements of the + struct...but a few macros and a little fixed-point math will do + wonders for ya. + + type bits: + F E D C B A 9 8 7 6 5 4 3 2 1 0 + | | | | | + | | +-+-+-- 0 = sharp-edged checkerboard + | | 1 = soft diamonds + | | 2 = radial waves + | | 3-7 = undefined + | +-- gradient #2 inverted? + +-- alternating columns inverted? + */ +static struct background_pattern { + ush type; + int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */ + int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/ +} bg[] = { + {0, 1,1, 16,16}, /* checkered: white vs. light gray (basic) */ + {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */ + {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */ + {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */ + {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */ + {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */ + {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */ + {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */ + {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */ + {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */ + {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */ + {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */ + {1, 3,0, 0,0}, /* diamonds: medium green vs. black */ + {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */ + {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */ + {2, 16, 256, 100, 250}, /* radial: very tight spiral */ + {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */ +}; +static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern); + + +/* X-specific variables */ +static char *displayname; +static XImage *ximage; +static Display *display; +static int depth; +static Visual *visual; +static XVisualInfo *visual_list; +static int RShift, GShift, BShift; +static ulg RMask, GMask, BMask; +static Window window; +static GC gc; +static Colormap colormap; + +static int have_nondefault_visual = FALSE; +static int have_colormap = FALSE; +static int have_window = FALSE; +static int have_gc = FALSE; + + + + +int main(int argc, char **argv) +{ +#ifdef sgi + char tmpline[80]; +#endif + char *p, *bgstr = NULL; + int rc, alen, flen; + int error = 0; + int timing = FALSE; + int have_bg = FALSE; +#ifdef FEATURE_LOOP + int loop = FALSE; + long loop_interval = -1; /* seconds (100,000 max) */ +#endif + double LUT_exponent; /* just the lookup table */ + double CRT_exponent = 2.2; /* just the monitor */ + double default_display_exponent; /* whole display system */ + XEvent e; + KeySym k; + + + /* First initialize a few things, just to be sure--memset takes care of + * default background color (black), booleans (FALSE), pointers (NULL), + * etc. */ + + displayname = (char *)NULL; + filename = (char *)NULL; + memset(&rpng2_info, 0, sizeof(mainprog_info)); + + + /* Set the default value for our display-system exponent, i.e., the + * product of the CRT exponent and the exponent corresponding to + * the frame-buffer's lookup table (LUT), if any. This is not an + * exhaustive list of LUT values (e.g., OpenStep has a lot of weird + * ones), but it should cover 99% of the current possibilities. */ + +#if defined(NeXT) + /* third-party utilities can modify the default LUT exponent */ + LUT_exponent = 1.0 / 2.2; + /* + if (some_next_function_that_returns_gamma(&next_gamma)) + LUT_exponent = 1.0 / next_gamma; + */ +#elif defined(sgi) + LUT_exponent = 1.0 / 1.7; + /* there doesn't seem to be any documented function to + * get the "gamma" value, so we do it the hard way */ + infile = fopen("/etc/config/system.glGammaVal", "r"); + if (infile) { + double sgi_gamma; + + fgets(tmpline, 80, infile); + fclose(infile); + sgi_gamma = atof(tmpline); + if (sgi_gamma > 0.0) + LUT_exponent = 1.0 / sgi_gamma; + } +#elif defined(Macintosh) + LUT_exponent = 1.8 / 2.61; + /* + if (some_mac_function_that_returns_gamma(&mac_gamma)) + LUT_exponent = mac_gamma / 2.61; + */ +#else + LUT_exponent = 1.0; /* assume no LUT: most PCs */ +#endif + + /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ + default_display_exponent = LUT_exponent * CRT_exponent; + + + /* If the user has set the SCREEN_GAMMA environment variable as suggested + * (somewhat imprecisely) in the libpng documentation, use that; otherwise + * use the default value we just calculated. Either way, the user may + * override this via a command-line option. */ + + if ((p = getenv("SCREEN_GAMMA")) != NULL) + rpng2_info.display_exponent = atof(p); + else + rpng2_info.display_exponent = default_display_exponent; + + + /* Now parse the command line for options and the PNG filename. */ + + while (*++argv && !error) { + if (!strncmp(*argv, "-display", 2)) { + if (!*++argv) + ++error; + else + displayname = *argv; + } else if (!strncmp(*argv, "-gamma", 2)) { + if (!*++argv) + ++error; + else { + rpng2_info.display_exponent = atof(*argv); + if (rpng2_info.display_exponent <= 0.0) + ++error; + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { + if (!*++argv) + ++error; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + have_bg = TRUE; + bg_image = FALSE; + } + } + } else if (!strncmp(*argv, "-bgpat", 4)) { + if (!*++argv) + ++error; + else { + pat = atoi(*argv); + if (pat >= 0 && pat < num_bgpat) { + bg_image = TRUE; + have_bg = FALSE; + } else + ++error; + } + } else if (!strncmp(*argv, "-usleep", 2)) { + if (!*++argv) + ++error; + else { + usleep_duration = (ulg)atol(*argv); + demo_timing = TRUE; + } + } else if (!strncmp(*argv, "-pause", 2)) { + pause_after_pass = TRUE; + } else if (!strncmp(*argv, "-timing", 2)) { + timing = TRUE; +#ifdef FEATURE_LOOP + } else if (!strncmp(*argv, "-loop", 2)) { + loop = TRUE; + if (!argv[1] || !is_number(argv[1])) + loop_interval = 2; + else { + ++argv; + loop_interval = atol(*argv); + if (loop_interval < 0) + loop_interval = 2; + else if (loop_interval > 100000) /* bit more than one day */ + loop_interval = 100000; + } +#endif + } else { + if (**argv != '-') { + filename = *argv; + if (argv[1]) /* shouldn't be any more args after filename */ + ++error; + } else + ++error; /* not expecting any other options */ + } + } + + if (!filename) + ++error; + + + /* print usage screen if any errors up to this point */ + + if (error) { + fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); + readpng2_version_info(); + fprintf(stderr, "\n" + "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n" +#ifdef FEATURE_LOOP + " %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n" +#else + " %*s [-usleep dur | -timing] [-pause] file.png\n\n" +#endif + " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" + " exp \ttransfer-function exponent (``gamma'') of the display\n" + "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" + "\t\t to the product of the lookup-table exponent (varies)\n" + "\t\t and the CRT exponent (usually 2.2); must be positive\n" + " bg \tdesired background color in 7-character hex RGB format\n" + "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" + "\t\t used with transparent images; overrides -bgpat\n" + " pat \tdesired background pattern number (0-%d); used with\n" + "\t\t transparent images; overrides -bgcolor\n" +#ifdef FEATURE_LOOP + " -loop\tloops through background images after initial display\n" + "\t\t is complete (depends on -bgpat)\n" + " sec \tseconds to display each background image (default = 2)\n" +#endif + " dur \tduration in microseconds to wait after displaying each\n" + "\t\t row (for demo purposes)\n" + " -timing\tenables delay for every block read, to simulate modem\n" + "\t\t download of image (~36 Kbps)\n" + " -pause\tpauses after displaying each pass until mouse clicked\n" + "\nPress Q, Esc or mouse button 1 (within image window, after image\n" + "is displayed) to quit.\n" + "\n", PROGNAME, + (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1); + exit(1); + } + + + if (!(infile = fopen(filename, "rb"))) { + fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); + ++error; + } else { + incount = fread(inbuf, 1, INBUFSIZE, infile); + if (incount < 8 || !readpng2_check_sig(inbuf, 8)) { + fprintf(stderr, PROGNAME + ": [%s] is not a PNG file: incorrect signature\n", + filename); + ++error; + } else if ((rc = readpng2_init(&rpng2_info)) != 0) { + switch (rc) { + case 2: + fprintf(stderr, PROGNAME + ": [%s] has bad IHDR (libpng longjmp)\n", filename); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown readpng2_init() error\n"); + break; + } + ++error; + } else { + Trace((stderr, "about to call XOpenDisplay()\n")) + display = XOpenDisplay(displayname); + if (!display) { + readpng2_cleanup(&rpng2_info); + fprintf(stderr, PROGNAME ": can't open X display [%s]\n", + displayname? displayname : "default"); + ++error; + } + } + if (error) + fclose(infile); + } + + + if (error) { + fprintf(stderr, PROGNAME ": aborting.\n"); + exit(2); + } + + + /* set the title-bar string, but make sure buffer doesn't overflow */ + + alen = strlen(appname); + flen = strlen(filename); + if (alen + flen + 3 > 1023) + sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); + else + sprintf(titlebar, "%s: %s", appname, filename); + + + /* set some final rpng2_info variables before entering main data loop */ + + if (have_bg) { + unsigned r, g, b; /* this approach quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + rpng2_info.bg_red = (uch)r; + rpng2_info.bg_green = (uch)g; + rpng2_info.bg_blue = (uch)b; + } else + rpng2_info.need_bgcolor = TRUE; + + rpng2_info.state = kPreInit; + rpng2_info.mainprog_init = rpng2_x_init; + rpng2_info.mainprog_display_row = rpng2_x_display_row; + rpng2_info.mainprog_finish_display = rpng2_x_finish_display; + + + /* OK, this is the fun part: call readpng2_decode_data() at the start of + * the loop to deal with our first buffer of data (read in above to verify + * that the file is a PNG image), then loop through the file and continue + * calling the same routine to handle each chunk of data. It in turn + * passes the data to libpng, which will invoke one or more of our call- + * backs as decoded data become available. We optionally call sleep() for + * one second per iteration to simulate downloading the image via an analog + * modem. */ + + for (;;) { + Trace((stderr, "about to call readpng2_decode_data()\n")) + if (readpng2_decode_data(&rpng2_info, inbuf, incount)) + ++error; + Trace((stderr, "done with readpng2_decode_data()\n")) + + if (error || incount != INBUFSIZE || rpng2_info.state == kDone) { + if (rpng2_info.state == kDone) { + Trace((stderr, "done decoding PNG image\n")) + } else if (ferror(infile)) { + fprintf(stderr, PROGNAME + ": error while reading PNG image file\n"); + exit(3); + } else if (feof(infile)) { + fprintf(stderr, PROGNAME ": end of file reached " + "(unexpectedly) while reading PNG image file\n"); + exit(3); + } else /* if (error) */ { + // will print error message below + } + break; + } + + if (timing) + sleep(1); + + incount = fread(inbuf, 1, INBUFSIZE, infile); + } + + + /* clean up PNG stuff and report any decoding errors */ + + fclose(infile); + Trace((stderr, "about to call readpng2_cleanup()\n")) + readpng2_cleanup(&rpng2_info); + + if (error) { + fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n"); + exit(3); + } + + +#ifdef FEATURE_LOOP + + if (loop && bg_image) { + Trace((stderr, "entering -loop loop (FEATURE_LOOP)\n")) + for (;;) { + int i, use_sleep; + struct timeval now, then; + + /* get current time and add loop_interval to get target time */ + if (gettimeofday(&then, NULL) == 0) { + then.tv_sec += loop_interval; + use_sleep = FALSE; + } else + use_sleep = TRUE; + + /* do quick check for a quit event but don't wait for it */ + /* GRR BUG: should also check for Expose events and redraw... */ + if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &e)) + if (QUIT(e,k)) + break; + + /* generate next background image */ + if (++pat >= num_bgpat) + pat = 0; + rpng2_x_reload_bg_image(); + + /* wait for timeout, using whatever means are available */ + if (use_sleep || gettimeofday(&now, NULL) != 0) { + for (i = loop_interval; i > 0; --i) { + sleep(1); + /* GRR BUG: also need to check for Expose (and redraw!) */ + if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, + &e) && QUIT(e,k)) + break; + } + } else { + /* Y2038 BUG! */ + if (now.tv_sec < then.tv_sec || + (now.tv_sec == then.tv_sec && now.tv_usec < then.tv_usec)) + { + int quit = FALSE; + long seconds_to_go = then.tv_sec - now.tv_sec; + long usleep_usec; + + /* basically chew up most of remaining loop-interval with + * calls to sleep(1) interleaved with checks for quit + * events, but also recalc time-to-go periodically; when + * done, clean up any remaining time with usleep() call + * (could also use SIGALRM, but signals are a pain...) */ + while (seconds_to_go-- > 1) { + int seconds_done = 0; + + for (i = seconds_to_go; i > 0 && !quit; --i) { + sleep(1); + /* GRR BUG: need to check for Expose and redraw */ + if (XCheckMaskEvent(display, KeyPressMask | + ButtonPressMask, &e) && QUIT(e,k)) + quit = TRUE; + if (++seconds_done > 1000) + break; /* time to redo seconds_to_go meas. */ + } + if (quit) + break; + + /* OK, more than 1000 seconds since last check: + * correct the time-to-go measurement for drift */ + if (gettimeofday(&now, NULL) == 0) { + if (now.tv_sec >= then.tv_sec) + break; + seconds_to_go = then.tv_sec - now.tv_sec; + } else + ++seconds_to_go; /* restore what we subtracted */ + } + if (quit) + break; /* breaks outer do-loop, skips redisplay */ + + /* since difference between "now" and "then" is already + * eaten up to within a couple of seconds, don't need to + * worry about overflow--but might have overshot (neg.) */ + if (gettimeofday(&now, NULL) == 0) { + usleep_usec = 1000000L*(then.tv_sec - now.tv_sec) + + then.tv_usec - now.tv_usec; + if (usleep_usec > 0) + usleep((ulg)usleep_usec); + } + } + } + + /* composite image against new background and display (note that + * we do not take into account the time spent doing this...) */ + rpng2_x_redisplay_image (0, 0, rpng2_info.width, rpng2_info.height); + } + + } else /* FALL THROUGH and do the normal thing */ + +#endif /* FEATURE_LOOP */ + + /* wait for the user to tell us when to quit */ + + if (rpng2_info.state >= kWindowInit) { + Trace((stderr, "entering final wait-for-quit-event loop\n")) + do { + XNextEvent(display, &e); + if (e.type == Expose) { + XExposeEvent *ex = (XExposeEvent *)&e; + rpng2_x_redisplay_image (ex->x, ex->y, ex->width, ex->height); + } + } while (!QUIT(e,k)); + } else { + fprintf(stderr, PROGNAME ": init callback never called: probable " + "libpng error while decoding PNG metadata\n"); + exit(4); + } + + + /* we're done: clean up all image and X resources and go away */ + + Trace((stderr, "about to call rpng2_x_cleanup()\n")) + rpng2_x_cleanup(); + + return 0; +} + + + + + +/* this function is called by readpng2_info_callback() in readpng2.c, which + * in turn is called by libpng after all of the pre-IDAT chunks have been + * read and processed--i.e., we now have enough info to finish initializing */ + +static void rpng2_x_init(void) +{ + ulg i; + ulg rowbytes = rpng2_info.rowbytes; + + Trace((stderr, "beginning rpng2_x_init()\n")) + Trace((stderr, " rowbytes = %d\n", rpng2_info.rowbytes)) + Trace((stderr, " width = %ld\n", rpng2_info.width)) + Trace((stderr, " height = %ld\n", rpng2_info.height)) + + rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height); + if (!rpng2_info.image_data) { + readpng2_cleanup(&rpng2_info); + return; + } + + rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *)); + if (!rpng2_info.row_pointers) { + free(rpng2_info.image_data); + rpng2_info.image_data = NULL; + readpng2_cleanup(&rpng2_info); + return; + } + + for (i = 0; i < rpng2_info.height; ++i) + rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes; + + + /* do the basic X initialization stuff, make the window, and fill it with + * the user-specified, file-specified or default background color or + * pattern */ + + if (rpng2_x_create_window()) { + + /* GRR TEMPORARY HACK: this is fundamentally no different from cases + * above; libpng should call our error handler to longjmp() back to us + * when png_ptr goes away. If we/it segfault instead, seems like a + * libpng bug... */ + + /* we're here via libpng callback, so if window fails, clean and bail */ + readpng2_cleanup(&rpng2_info); + rpng2_x_cleanup(); + exit(2); + } + + rpng2_info.state = kWindowInit; +} + + + + + +static int rpng2_x_create_window(void) +{ + ulg bg_red = rpng2_info.bg_red; + ulg bg_green = rpng2_info.bg_green; + ulg bg_blue = rpng2_info.bg_blue; + ulg bg_pixel = 0L; + ulg attrmask; + int need_colormap = FALSE; + int screen, pad; + uch *xdata; + Window root; + XEvent e; + XGCValues gcvalues; + XSetWindowAttributes attr; + XTextProperty windowName, *pWindowName = &windowName; + XTextProperty iconName, *pIconName = &iconName; + XVisualInfo visual_info; + XSizeHints *size_hints; + XWMHints *wm_hints; + XClassHint *class_hints; + + + Trace((stderr, "beginning rpng2_x_create_window()\n")) + + screen = DefaultScreen(display); + depth = DisplayPlanes(display, screen); + root = RootWindow(display, screen); + +#ifdef DEBUG + XSynchronize(display, True); +#endif + + if (depth != 16 && depth != 24 && depth != 32) { + int visuals_matched = 0; + + Trace((stderr, "default depth is %d: checking other visuals\n", + depth)) + + /* 24-bit first */ + visual_info.screen = screen; + visual_info.depth = 24; + visual_list = XGetVisualInfo(display, + VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched); + if (visuals_matched == 0) { +/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */ + fprintf(stderr, "default screen depth %d not supported, and no" + " 24-bit visuals found\n", depth); + return 2; + } + Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n", + visuals_matched)) + visual = visual_list[0].visual; + depth = visual_list[0].depth; +/* + colormap_size = visual_list[0].colormap_size; + visual_class = visual->class; + visualID = XVisualIDFromVisual(visual); + */ + have_nondefault_visual = TRUE; + need_colormap = TRUE; + } else { + XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info); + visual = visual_info.visual; + } + + RMask = visual->red_mask; + GMask = visual->green_mask; + BMask = visual->blue_mask; + +/* GRR: add/check 8-bit support */ + if (depth == 8 || need_colormap) { + colormap = XCreateColormap(display, root, visual, AllocNone); + if (!colormap) { + fprintf(stderr, "XCreateColormap() failed\n"); + return 2; + } + have_colormap = TRUE; + if (depth == 8) + bg_image = FALSE; /* gradient just wastes palette entries */ + } + if (depth == 15 || depth == 16) { + RShift = 15 - rpng2_x_msb(RMask); /* these are right-shifts */ + GShift = 15 - rpng2_x_msb(GMask); + BShift = 15 - rpng2_x_msb(BMask); + } else if (depth > 16) { + RShift = rpng2_x_msb(RMask) - 7; /* these are left-shifts */ + GShift = rpng2_x_msb(GMask) - 7; + BShift = rpng2_x_msb(BMask) - 7; + } + if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) { + fprintf(stderr, "rpng2 internal logic error: negative X shift(s)!\n"); + return 2; + } + +/*--------------------------------------------------------------------------- + Finally, create the window. + ---------------------------------------------------------------------------*/ + + attr.backing_store = Always; + attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask; + attrmask = CWBackingStore | CWEventMask; + if (have_nondefault_visual) { + attr.colormap = colormap; + attr.background_pixel = 0; + attr.border_pixel = 1; + attrmask |= CWColormap | CWBackPixel | CWBorderPixel; + } + + window = XCreateWindow(display, root, 0, 0, rpng2_info.width, + rpng2_info.height, 0, depth, InputOutput, visual, attrmask, &attr); + + if (window == None) { + fprintf(stderr, "XCreateWindow() failed\n"); + return 2; + } else + have_window = TRUE; + + if (depth == 8) + XSetWindowColormap(display, window, colormap); + + if (!XStringListToTextProperty(&window_name, 1, pWindowName)) + pWindowName = NULL; + if (!XStringListToTextProperty(&icon_name, 1, pIconName)) + pIconName = NULL; + + /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */ + + if ((size_hints = XAllocSizeHints()) != NULL) { + /* window will not be resizable */ + size_hints->flags = PMinSize | PMaxSize; + size_hints->min_width = size_hints->max_width = (int)rpng2_info.width; + size_hints->min_height = size_hints->max_height = + (int)rpng2_info.height; + } + + if ((wm_hints = XAllocWMHints()) != NULL) { + wm_hints->initial_state = NormalState; + wm_hints->input = True; + /* wm_hints->icon_pixmap = icon_pixmap; */ + wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ; + } + + if ((class_hints = XAllocClassHint()) != NULL) { + class_hints->res_name = res_name; + class_hints->res_class = res_class; + } + + XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0, + size_hints, wm_hints, class_hints); + + /* various properties and hints no longer needed; free memory */ + if (pWindowName) + XFree(pWindowName->value); + if (pIconName) + XFree(pIconName->value); + if (size_hints) + XFree(size_hints); + if (wm_hints) + XFree(wm_hints); + if (class_hints) + XFree(class_hints); + + XMapWindow(display, window); + + gc = XCreateGC(display, window, 0, &gcvalues); + have_gc = TRUE; + +/*--------------------------------------------------------------------------- + Allocate memory for the X- and display-specific version of the image. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + xdata = (uch *)malloc(4*rpng2_info.width*rpng2_info.height); + pad = 32; + } else if (depth == 16) { + xdata = (uch *)malloc(2*rpng2_info.width*rpng2_info.height); + pad = 16; + } else /* depth == 8 */ { + xdata = (uch *)malloc(rpng2_info.width*rpng2_info.height); + pad = 8; + } + + if (!xdata) { + fprintf(stderr, PROGNAME ": unable to allocate image memory\n"); + return 4; + } + + ximage = XCreateImage(display, visual, depth, ZPixmap, 0, + (char *)xdata, rpng2_info.width, rpng2_info.height, pad, 0); + + if (!ximage) { + fprintf(stderr, PROGNAME ": XCreateImage() failed\n"); + free(xdata); + return 3; + } + + /* to avoid testing the byte order every pixel (or doubling the size of + * the drawing routine with a giant if-test), we arbitrarily set the byte + * order to MSBFirst and let Xlib worry about inverting things on little- + * endian machines (e.g., Linux/x86, old VAXen, etc.)--this is not the + * most efficient approach (the giant if-test would be better), but in + * the interest of clarity, we'll take the easy way out... */ + + ximage->byte_order = MSBFirst; + +/*--------------------------------------------------------------------------- + Fill window with the specified background color (default is black) or + faked "background image" (but latter is disabled if 8-bit; gradients + just waste palette entries). + ---------------------------------------------------------------------------*/ + + if (bg_image) + rpng2_x_load_bg_image(); /* resets bg_image if fails */ + + if (!bg_image) { + if (depth == 24 || depth == 32) { + bg_pixel = (bg_red << RShift) | + (bg_green << GShift) | + (bg_blue << BShift); + } else if (depth == 16) { + bg_pixel = (((bg_red << 8) >> RShift) & RMask) | + (((bg_green << 8) >> GShift) & GMask) | + (((bg_blue << 8) >> BShift) & BMask); + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + XSetForeground(display, gc, bg_pixel); + XFillRectangle(display, window, gc, 0, 0, rpng2_info.width, + rpng2_info.height); + } + +/*--------------------------------------------------------------------------- + Wait for first Expose event to do any drawing, then flush and return. + ---------------------------------------------------------------------------*/ + + do + XNextEvent(display, &e); + while (e.type != Expose || e.xexpose.count); + + XFlush(display); + + return 0; + +} /* end function rpng2_x_create_window() */ + + + + + +static int rpng2_x_load_bg_image(void) +{ + uch *src; + char *dest; + uch r1, r2, g1, g2, b1, b2; + uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv; + int k, hmax, max; + int xidx, yidx, yidx_max; + int even_odd_vert, even_odd_horiz, even_odd; + int invert_gradient2 = (bg[pat].type & 0x08); + int invert_column; + int ximage_rowbytes = ximage->bytes_per_line; + ulg i, row; + ulg pixel; + +/*--------------------------------------------------------------------------- + Allocate buffer for fake background image to be used with transparent + images; if this fails, revert to plain background color. + ---------------------------------------------------------------------------*/ + + bg_rowbytes = 3 * rpng2_info.width; + bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height); + if (!bg_data) { + fprintf(stderr, PROGNAME + ": unable to allocate memory for background image\n"); + bg_image = 0; + return 1; + } + + bgscale = (pat == 0)? 8 : bgscale_default; + yidx_max = bgscale - 1; + +/*--------------------------------------------------------------------------- + Vertical gradients (ramps) in NxN squares, alternating direction and + colors (N == bgscale). + ---------------------------------------------------------------------------*/ + + if ((bg[pat].type & 0x07) == 0) { + uch r1_min = rgb[bg[pat].rgb1_min].r; + uch g1_min = rgb[bg[pat].rgb1_min].g; + uch b1_min = rgb[bg[pat].rgb1_min].b; + uch r2_min = rgb[bg[pat].rgb2_min].r; + uch g2_min = rgb[bg[pat].rgb2_min].g; + uch b2_min = rgb[bg[pat].rgb2_min].b; + int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min; + int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min; + int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min; + int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min; + int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min; + int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = (int)(row % bgscale); + even_odd_vert = (int)((row / bgscale) & 1); + + r1 = r1_min + (r1_diff * yidx) / yidx_max; + g1 = g1_min + (g1_diff * yidx) / yidx_max; + b1 = b1_min + (b1_diff * yidx) / yidx_max; + r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max; + g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max; + b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max; + + r2 = r2_min + (r2_diff * yidx) / yidx_max; + g2 = g2_min + (g2_diff * yidx) / yidx_max; + b2 = b2_min + (b2_diff * yidx) / yidx_max; + r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max; + g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max; + b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max; + + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + even_odd_horiz = (int)((i / bgscale) & 1); + even_odd = even_odd_vert ^ even_odd_horiz; + invert_column = + (even_odd_horiz && (bg[pat].type & 0x10)); + if (even_odd == 0) { /* gradient #1 */ + if (invert_column) { + *dest++ = r1_inv; + *dest++ = g1_inv; + *dest++ = b1_inv; + } else { + *dest++ = r1; + *dest++ = g1; + *dest++ = b1; + } + } else { /* gradient #2 */ + if ((invert_column && invert_gradient2) || + (!invert_column && !invert_gradient2)) + { + *dest++ = r2; /* not inverted or */ + *dest++ = g2; /* doubly inverted */ + *dest++ = b2; + } else { + *dest++ = r2_inv; + *dest++ = g2_inv; /* singly inverted */ + *dest++ = b2_inv; + } + } + } + } + +/*--------------------------------------------------------------------------- + Soft gradient-diamonds with scale = bgscale. Code contributed by Adam + M. Costello. + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 1) { + + hmax = (bgscale-1)/2; /* half the max weight of a color */ + max = 2*hmax; /* the max weight of a color */ + + r1 = rgb[bg[pat].rgb1_max].r; + g1 = rgb[bg[pat].rgb1_max].g; + b1 = rgb[bg[pat].rgb1_max].b; + r2 = rgb[bg[pat].rgb2_max].r; + g2 = rgb[bg[pat].rgb2_max].g; + b2 = rgb[bg[pat].rgb2_max].b; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = (int)(row % bgscale); + if (yidx > hmax) + yidx = bgscale-1 - yidx; + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + xidx = (int)(i % bgscale); + if (xidx > hmax) + xidx = bgscale-1 - xidx; + k = xidx + yidx; + *dest++ = (k*r1 + (max-k)*r2) / max; + *dest++ = (k*g1 + (max-k)*g2) / max; + *dest++ = (k*b1 + (max-k)*b2) / max; + } + } + +/*--------------------------------------------------------------------------- + Radial "starburst" with azimuthal sinusoids; [eventually number of sinu- + soids will equal bgscale?]. This one is slow but very cool. Code con- + tributed by Pieter S. van der Meulen (originally in Smalltalk). + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 2) { + uch ch; + int ii, x, y, hw, hh, grayspot; + double freq, rotate, saturate, gray, intensity; + double angle=0.0, aoffset=0.0, maxDist, dist; + double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t; + + fprintf(stderr, "%s: computing radial background...", + PROGNAME); + fflush(stderr); + + hh = (int)(rpng2_info.height / 2); + hw = (int)(rpng2_info.width / 2); + + /* variables for radial waves: + * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED] + * freq: number of color beams originating from the center + * grayspot: size of the graying center area (anti-alias) + * rotate: rotation of the beams as a function of radius + * saturate: saturation of beams' shape azimuthally + */ + angle = CLIP(angle, 0.0, 360.0); + grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw)); + freq = MAX((double)bg[pat].bg_freq, 0.0); + saturate = (double)bg[pat].bg_bsat * 0.1; + rotate = (double)bg[pat].bg_brot * 0.1; + gray = 0.0; + intensity = 0.0; + maxDist = (double)((hw*hw) + (hh*hh)); + + for (row = 0; row < rpng2_info.height; ++row) { + y = (int)(row - hh); + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + x = (int)(i - hw); + angle = (x == 0)? PI_2 : atan((double)y / (double)x); + gray = (double)MAX(ABS(y), ABS(x)) / grayspot; + gray = MIN(1.0, gray); + dist = (double)((x*x) + (y*y)) / maxDist; + intensity = cos((angle+(rotate*dist*PI)) * freq) * + gray * saturate; + intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5; + hue = (angle + PI) * INV_PI_360 + aoffset; + s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh)); + s = MIN(MAX(s,0.0), 1.0); + v = MIN(MAX(intensity,0.0), 1.0); + + if (s == 0.0) { + ch = (uch)(v * 255.0); + *dest++ = ch; + *dest++ = ch; + *dest++ = ch; + } else { + if ((hue < 0.0) || (hue >= 360.0)) + hue -= (((int)(hue / 360.0)) * 360.0); + hue /= 60.0; + ii = (int)hue; + f = hue - (double)ii; + p = (1.0 - s) * v; + q = (1.0 - (s * f)) * v; + t = (1.0 - (s * (1.0 - f))) * v; + if (ii == 0) { red = v; green = t; blue = p; } + else if (ii == 1) { red = q; green = v; blue = p; } + else if (ii == 2) { red = p; green = v; blue = t; } + else if (ii == 3) { red = p; green = q; blue = v; } + else if (ii == 4) { red = t; green = p; blue = v; } + else if (ii == 5) { red = v; green = p; blue = q; } + *dest++ = (uch)(red * 255.0); + *dest++ = (uch)(green * 255.0); + *dest++ = (uch)(blue * 255.0); + } + } + } + fprintf(stderr, "done.\n"); + fflush(stderr); + } + +/*--------------------------------------------------------------------------- + Blast background image to display buffer before beginning PNG decode. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + ulg red, green, blue; + int bpp = ximage->bits_per_pixel; + + for (row = 0; row < rpng2_info.height; ++row) { + src = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (bpp == 32) { /* slightly optimized version */ + for (i = rpng2_info.width; i > 0; --i) { + red = *src++; + green = *src++; + blue = *src++; + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } else { + for (i = rpng2_info.width; i > 0; --i) { + red = *src++; + green = *src++; + blue = *src++; + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + /* GRR BUG? this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + } + + } else if (depth == 16) { + ush red, green, blue; + + for (row = 0; row < rpng2_info.height; ++row) { + src = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + for (i = rpng2_info.width; i > 0; --i) { + red = ((ush)(*src) << 8); ++src; + green = ((ush)(*src) << 8); ++src; + blue = ((ush)(*src) << 8); ++src; + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.width, + rpng2_info.height); + + return 0; + +} /* end function rpng2_x_load_bg_image() */ + + + + + +static void rpng2_x_display_row(ulg row) +{ + uch bg_red = rpng2_info.bg_red; + uch bg_green = rpng2_info.bg_green; + uch bg_blue = rpng2_info.bg_blue; + uch *src, *src2=NULL; + char *dest; + uch r, g, b, a; + int ximage_rowbytes = ximage->bytes_per_line; + ulg i, pixel; + static int rows=0, prevpass=(-1); + static ulg firstrow; + +/*--------------------------------------------------------------------------- + rows and firstrow simply track how many rows (and which ones) have not + yet been displayed; alternatively, we could call XPutImage() for every + row and not bother with the records-keeping. + ---------------------------------------------------------------------------*/ + + Trace((stderr, "beginning rpng2_x_display_row()\n")) + + if (rpng2_info.pass != prevpass) { + if (pause_after_pass && rpng2_info.pass > 0) { + XEvent e; + KeySym k; + + fprintf(stderr, + "%s: end of pass %d of 7; click in image window to continue\n", + PROGNAME, prevpass + 1); + do + XNextEvent(display, &e); + while (!QUIT(e,k)); + } + fprintf(stderr, "%s: pass %d of 7\r", PROGNAME, rpng2_info.pass + 1); + fflush(stderr); + prevpass = rpng2_info.pass; + } + + if (rows == 0) + firstrow = row; /* first row that is not yet displayed */ + + ++rows; /* count of rows received but not yet displayed */ + +/*--------------------------------------------------------------------------- + Aside from the use of the rpng2_info struct, the lack of an outer loop + (over rows) and moving the XPutImage() call outside the "if (depth)" + tests, this routine is identical to rpng_x_display_image() in the non- + progressive version of the program. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + ulg red, green, blue; + int bpp = ximage->bits_per_pixel; + + src = rpng2_info.image_data + row*rpng2_info.rowbytes; + if (bg_image) + src2 = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (rpng2_info.channels == 3) { + for (i = rpng2_info.width; i > 0; --i) { + red = *src++; + green = *src++; + blue = *src++; + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG? this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + } else /* if (rpng2_info.channels == 4) */ { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (bg_image) { + bg_red = *src2++; + bg_green = *src2++; + bg_blue = *src2++; + } + if (a == 255) { + red = r; + green = g; + blue = b; + } else if (a == 0) { + red = bg_red; + green = bg_green; + blue = bg_blue; + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result into the + * first argument */ + alpha_composite(red, r, a, bg_red); + alpha_composite(green, g, a, bg_green); + alpha_composite(blue, b, a, bg_blue); + } + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG? this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + } + + } else if (depth == 16) { + ush red, green, blue; + + src = rpng2_info.row_pointers[row]; + if (bg_image) + src2 = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (rpng2_info.channels == 3) { + for (i = rpng2_info.width; i > 0; --i) { + red = ((ush)(*src) << 8); + ++src; + green = ((ush)(*src) << 8); + ++src; + blue = ((ush)(*src) << 8); + ++src; + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } else /* if (rpng2_info.channels == 4) */ { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (bg_image) { + bg_red = *src2++; + bg_green = *src2++; + bg_blue = *src2++; + } + if (a == 255) { + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } else if (a == 0) { + red = ((ush)bg_red << 8); + green = ((ush)bg_green << 8); + blue = ((ush)bg_blue << 8); + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result back into + * the first argument (== fg byte here: safe) */ + alpha_composite(r, r, a, bg_red); + alpha_composite(g, g, a, bg_green); + alpha_composite(b, b, a, bg_blue); + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + +/*--------------------------------------------------------------------------- + Display after every 16 rows or when on one of last two rows. (Region + may include previously displayed lines due to interlacing--i.e., not + contiguous. Also, second-to-last row is final one in interlaced images + with odd number of rows.) For demos, flush (and delay) after every 16th + row so "sparse" passes don't go twice as fast. + ---------------------------------------------------------------------------*/ + + if (demo_timing && (row - firstrow >= 16 || row >= rpng2_info.height-2)) { + XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0, + (int)firstrow, rpng2_info.width, row - firstrow + 1); + XFlush(display); + rows = 0; + usleep(usleep_duration); + } else + if (!demo_timing && ((rows & 0xf) == 0 || row >= rpng2_info.height-2)) { + XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0, + (int)firstrow, rpng2_info.width, row - firstrow + 1); + XFlush(display); + rows = 0; + } + +} + + + + + +static void rpng2_x_finish_display(void) +{ + Trace((stderr, "beginning rpng2_x_finish_display()\n")) + + /* last row has already been displayed by rpng2_x_display_row(), so we + * have nothing to do here except set a flag and let the user know that + * the image is done */ + + rpng2_info.state = kDone; + printf( + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); + fflush(stdout); +} + + + + + +static void rpng2_x_redisplay_image(ulg startcol, ulg startrow, + ulg width, ulg height) +{ + uch bg_red = rpng2_info.bg_red; + uch bg_green = rpng2_info.bg_green; + uch bg_blue = rpng2_info.bg_blue; + uch *src, *src2=NULL; + char *dest; + uch r, g, b, a; + ulg i, row, lastrow = 0; + ulg pixel; + int ximage_rowbytes = ximage->bytes_per_line; + + + Trace((stderr, "beginning display loop (image_channels == %d)\n", + rpng2_info.channels)) + Trace((stderr, " (width = %ld, rowbytes = %d, ximage_rowbytes = %d)\n", + rpng2_info.width, rpng2_info.rowbytes, ximage_rowbytes)) + Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel)) + Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst? + "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown"))) + +/*--------------------------------------------------------------------------- + Aside from the use of the rpng2_info struct and of src2 (for background + image), this routine is identical to rpng_x_display_image() in the non- + progressive version of the program--for the simple reason that redisplay + of the image against a new background happens after the image is fully + decoded and therefore is, by definition, non-progressive. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + ulg red, green, blue; + int bpp = ximage->bits_per_pixel; + + for (lastrow = row = startrow; row < startrow+height; ++row) { + src = rpng2_info.image_data + row*rpng2_info.rowbytes; + if (bg_image) + src2 = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (rpng2_info.channels == 3) { + for (i = rpng2_info.width; i > 0; --i) { + red = *src++; + green = *src++; + blue = *src++; +#ifdef NO_24BIT_MASKS + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#else + red = (RShift < 0)? red << (-RShift) : red >> RShift; + green = (GShift < 0)? green << (-GShift) : green >> GShift; + blue = (BShift < 0)? blue << (-BShift) : blue >> BShift; + pixel = (red & RMask) | (green & GMask) | (blue & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG */ + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift/RMask/etc. here, too) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#endif + } + + } else /* if (rpng2_info.channels == 4) */ { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (bg_image) { + bg_red = *src2++; + bg_green = *src2++; + bg_blue = *src2++; + } + if (a == 255) { + red = r; + green = g; + blue = b; + } else if (a == 0) { + red = bg_red; + green = bg_green; + blue = bg_blue; + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result into the + * first argument */ + alpha_composite(red, r, a, bg_red); + alpha_composite(green, g, a, bg_green); + alpha_composite(blue, b, a, bg_blue); + } +#ifdef NO_24BIT_MASKS + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#else + red = (RShift < 0)? red << (-RShift) : red >> RShift; + green = (GShift < 0)? green << (-GShift) : green >> GShift; + blue = (BShift < 0)? blue << (-BShift) : blue >> BShift; + pixel = (red & RMask) | (green & GMask) | (blue & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG */ + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift/RMask/etc. here, too) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#endif + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else if (depth == 16) { + ush red, green, blue; + + for (lastrow = row = startrow; row < startrow+height; ++row) { + src = rpng2_info.row_pointers[row]; + if (bg_image) + src2 = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (rpng2_info.channels == 3) { + for (i = rpng2_info.width; i > 0; --i) { + red = ((ush)(*src) << 8); + ++src; + green = ((ush)(*src) << 8); + ++src; + blue = ((ush)(*src) << 8); + ++src; + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } else /* if (rpng2_info.channels == 4) */ { + for (i = rpng2_info.width; i > 0; --i) { + r = *src++; + g = *src++; + b = *src++; + a = *src++; + if (bg_image) { + bg_red = *src2++; + bg_green = *src2++; + bg_blue = *src2++; + } + if (a == 255) { + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } else if (a == 0) { + red = ((ush)bg_red << 8); + green = ((ush)bg_green << 8); + blue = ((ush)bg_blue << 8); + } else { + /* this macro (from png.h) composites the foreground + * and background values and puts the result back into + * the first argument (== fg byte here: safe) */ + alpha_composite(r, r, a, bg_red); + alpha_composite(g, g, a, bg_green); + alpha_composite(b, b, a, bg_blue); + red = ((ush)r << 8); + green = ((ush)g << 8); + blue = ((ush)b << 8); + } + pixel = ((red >> RShift) & RMask) | + ((green >> GShift) & GMask) | + ((blue >> BShift) & BMask); + /* recall that we set ximage->byte_order = MSBFirst above */ + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + Trace((stderr, "calling final XPutImage()\n")) + if (lastrow < startrow+height) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, rpng2_info.height-lastrow); + XFlush(display); + } + +} /* end function rpng2_x_redisplay_image() */ + + + + + +#ifdef FEATURE_LOOP + +static void rpng2_x_reload_bg_image(void) +{ + char *dest; + uch r1, r2, g1, g2, b1, b2; + uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv; + int k, hmax, max; + int xidx, yidx, yidx_max; + int even_odd_vert, even_odd_horiz, even_odd; + int invert_gradient2 = (bg[pat].type & 0x08); + int invert_column; + ulg i, row; + + + bgscale = (pat == 0)? 8 : bgscale_default; + yidx_max = bgscale - 1; + +/*--------------------------------------------------------------------------- + Vertical gradients (ramps) in NxN squares, alternating direction and + colors (N == bgscale). + ---------------------------------------------------------------------------*/ + + if ((bg[pat].type & 0x07) == 0) { + uch r1_min = rgb[bg[pat].rgb1_min].r; + uch g1_min = rgb[bg[pat].rgb1_min].g; + uch b1_min = rgb[bg[pat].rgb1_min].b; + uch r2_min = rgb[bg[pat].rgb2_min].r; + uch g2_min = rgb[bg[pat].rgb2_min].g; + uch b2_min = rgb[bg[pat].rgb2_min].b; + int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min; + int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min; + int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min; + int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min; + int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min; + int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = (int)(row % bgscale); + even_odd_vert = (int)((row / bgscale) & 1); + + r1 = r1_min + (r1_diff * yidx) / yidx_max; + g1 = g1_min + (g1_diff * yidx) / yidx_max; + b1 = b1_min + (b1_diff * yidx) / yidx_max; + r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max; + g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max; + b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max; + + r2 = r2_min + (r2_diff * yidx) / yidx_max; + g2 = g2_min + (g2_diff * yidx) / yidx_max; + b2 = b2_min + (b2_diff * yidx) / yidx_max; + r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max; + g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max; + b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max; + + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + even_odd_horiz = (int)((i / bgscale) & 1); + even_odd = even_odd_vert ^ even_odd_horiz; + invert_column = + (even_odd_horiz && (bg[pat].type & 0x10)); + if (even_odd == 0) { /* gradient #1 */ + if (invert_column) { + *dest++ = r1_inv; + *dest++ = g1_inv; + *dest++ = b1_inv; + } else { + *dest++ = r1; + *dest++ = g1; + *dest++ = b1; + } + } else { /* gradient #2 */ + if ((invert_column && invert_gradient2) || + (!invert_column && !invert_gradient2)) + { + *dest++ = r2; /* not inverted or */ + *dest++ = g2; /* doubly inverted */ + *dest++ = b2; + } else { + *dest++ = r2_inv; + *dest++ = g2_inv; /* singly inverted */ + *dest++ = b2_inv; + } + } + } + } + +/*--------------------------------------------------------------------------- + Soft gradient-diamonds with scale = bgscale. Code contributed by Adam + M. Costello. + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 1) { + + hmax = (bgscale-1)/2; /* half the max weight of a color */ + max = 2*hmax; /* the max weight of a color */ + + r1 = rgb[bg[pat].rgb1_max].r; + g1 = rgb[bg[pat].rgb1_max].g; + b1 = rgb[bg[pat].rgb1_max].b; + r2 = rgb[bg[pat].rgb2_max].r; + g2 = rgb[bg[pat].rgb2_max].g; + b2 = rgb[bg[pat].rgb2_max].b; + + for (row = 0; row < rpng2_info.height; ++row) { + yidx = (int)(row % bgscale); + if (yidx > hmax) + yidx = bgscale-1 - yidx; + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + xidx = (int)(i % bgscale); + if (xidx > hmax) + xidx = bgscale-1 - xidx; + k = xidx + yidx; + *dest++ = (k*r1 + (max-k)*r2) / max; + *dest++ = (k*g1 + (max-k)*g2) / max; + *dest++ = (k*b1 + (max-k)*b2) / max; + } + } + +/*--------------------------------------------------------------------------- + Radial "starburst" with azimuthal sinusoids; [eventually number of sinu- + soids will equal bgscale?]. This one is slow but very cool. Code con- + tributed by Pieter S. van der Meulen (originally in Smalltalk). + ---------------------------------------------------------------------------*/ + + } else if ((bg[pat].type & 0x07) == 2) { + uch ch; + int ii, x, y, hw, hh, grayspot; + double freq, rotate, saturate, gray, intensity; + double angle=0.0, aoffset=0.0, maxDist, dist; + double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t; + + hh = (int)(rpng2_info.height / 2); + hw = (int)(rpng2_info.width / 2); + + /* variables for radial waves: + * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED] + * freq: number of color beams originating from the center + * grayspot: size of the graying center area (anti-alias) + * rotate: rotation of the beams as a function of radius + * saturate: saturation of beams' shape azimuthally + */ + angle = CLIP(angle, 0.0, 360.0); + grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw)); + freq = MAX((double)bg[pat].bg_freq, 0.0); + saturate = (double)bg[pat].bg_bsat * 0.1; + rotate = (double)bg[pat].bg_brot * 0.1; + gray = 0.0; + intensity = 0.0; + maxDist = (double)((hw*hw) + (hh*hh)); + + for (row = 0; row < rpng2_info.height; ++row) { + y = (int)(row - hh); + dest = (char *)bg_data + row*bg_rowbytes; + for (i = 0; i < rpng2_info.width; ++i) { + x = (int)(i - hw); + angle = (x == 0)? PI_2 : atan((double)y / (double)x); + gray = (double)MAX(ABS(y), ABS(x)) / grayspot; + gray = MIN(1.0, gray); + dist = (double)((x*x) + (y*y)) / maxDist; + intensity = cos((angle+(rotate*dist*PI)) * freq) * + gray * saturate; + intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5; + hue = (angle + PI) * INV_PI_360 + aoffset; + s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh)); + s = MIN(MAX(s,0.0), 1.0); + v = MIN(MAX(intensity,0.0), 1.0); + + if (s == 0.0) { + ch = (uch)(v * 255.0); + *dest++ = ch; + *dest++ = ch; + *dest++ = ch; + } else { + if ((hue < 0.0) || (hue >= 360.0)) + hue -= (((int)(hue / 360.0)) * 360.0); + hue /= 60.0; + ii = (int)hue; + f = hue - (double)ii; + p = (1.0 - s) * v; + q = (1.0 - (s * f)) * v; + t = (1.0 - (s * (1.0 - f))) * v; + if (ii == 0) { red = v; green = t; blue = p; } + else if (ii == 1) { red = q; green = v; blue = p; } + else if (ii == 2) { red = p; green = v; blue = t; } + else if (ii == 3) { red = p; green = q; blue = v; } + else if (ii == 4) { red = t; green = p; blue = v; } + else if (ii == 5) { red = v; green = p; blue = q; } + *dest++ = (uch)(red * 255.0); + *dest++ = (uch)(green * 255.0); + *dest++ = (uch)(blue * 255.0); + } + } + } + } + +} /* end function rpng2_x_reload_bg_image() */ + + + + + +static int is_number(char *p) +{ + while (*p) { + if (!isdigit(*p)) + return FALSE; + ++p; + } + return TRUE; +} + +#endif /* FEATURE_LOOP */ + + + + + +static void rpng2_x_cleanup(void) +{ + if (bg_image && bg_data) { + free(bg_data); + bg_data = NULL; + } + + if (rpng2_info.image_data) { + free(rpng2_info.image_data); + rpng2_info.image_data = NULL; + } + + if (rpng2_info.row_pointers) { + free(rpng2_info.row_pointers); + rpng2_info.row_pointers = NULL; + } + + if (ximage) { + if (ximage->data) { + free(ximage->data); /* we allocated it, so we free it */ + ximage->data = (char *)NULL; /* instead of XDestroyImage() */ + } + XDestroyImage(ximage); + ximage = NULL; + } + + if (have_gc) + XFreeGC(display, gc); + + if (have_window) + XDestroyWindow(display, window); + + if (have_colormap) + XFreeColormap(display, colormap); + + if (have_nondefault_visual) + XFree(visual_list); +} + + + + + +static int rpng2_x_msb(ulg u32val) +{ + int i; + + for (i = 31; i >= 0; --i) { + if (u32val & 0x80000000L) + break; + u32val <<= 1; + } + return i; +} diff --git a/extern/libpng/include/contrib/gregbook/toucan.png b/extern/libpng/include/contrib/gregbook/toucan.png new file mode 100644 index 0000000000000000000000000000000000000000..03960d4939938541ca3f8efee4bf13ffdecbb2f5 GIT binary patch literal 12901 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 z916my +#include +#include +#include /* for jmpbuf declaration in writepng.h */ +#include + +#ifdef DOS_OS2_W32 +# include /* for isatty(), setmode() prototypes */ +# include /* O_BINARY for fdopen() without text translation */ +# ifdef __EMX__ +# ifndef getch +# define getch() _read_kbd(0, 1, 0) /* need getche() */ +# endif +# else /* !__EMX__ */ +# ifdef __GO32__ +# include +# define getch() getkey() /* GRR: need getche() */ +# else +# include /* for getche() console input */ +# endif +# endif /* ?__EMX__ */ +# define FGETS(buf,len,stream) dos_kbd_gets(buf,len) +#else +# include /* for isatty() prototype */ +# define FGETS fgets +#endif + +/* #define DEBUG : this enables the Trace() macros */ + +/* #define FORBID_LATIN1_CTRL : this requires the user to re-enter any + text that includes control characters discouraged by the PNG spec; text + that includes an escape character (27) must be re-entered regardless */ + +#include "writepng.h" /* typedefs, common macros, writepng prototypes */ + + + +/* local prototypes */ + +static int wpng_isvalid_latin1(uch *p, int len); +static void wpng_cleanup(void); + +#ifdef DOS_OS2_W32 + static char *dos_kbd_gets(char *buf, int len); +#endif + + + +static mainprog_info wpng_info; /* lone global */ + + + +int main(int argc, char **argv) +{ +#ifndef DOS_OS2_W32 + FILE *keybd; +#endif +#ifdef sgi + FILE *tmpfile; /* or we could just use keybd, since no overlap */ + char tmpline[80]; +#endif + char *inname = NULL, outname[256]; + char *p, pnmchar, pnmline[256]; + char *bgstr, *textbuf = NULL; + ulg rowbytes; + int rc, len = 0; + int error = 0; + int text = FALSE; + int maxval; + double LUT_exponent; /* just the lookup table */ + double CRT_exponent = 2.2; /* just the monitor */ + double default_display_exponent; /* whole display system */ + double default_gamma = 0.0; + + + wpng_info.infile = NULL; + wpng_info.outfile = NULL; + wpng_info.image_data = NULL; + wpng_info.row_pointers = NULL; + wpng_info.filter = FALSE; + wpng_info.interlaced = FALSE; + wpng_info.have_bg = FALSE; + wpng_info.have_time = FALSE; + wpng_info.have_text = 0; + wpng_info.gamma = 0.0; + + + /* First get the default value for our display-system exponent, i.e., + * the product of the CRT exponent and the exponent corresponding to + * the frame-buffer's lookup table (LUT), if any. If the PNM image + * looks correct on the user's display system, its file gamma is the + * inverse of this value. (Note that this is not an exhaustive list + * of LUT values--e.g., OpenStep has a lot of weird ones--but it should + * cover 99% of the current possibilities. This section must ensure + * that default_display_exponent is positive.) */ + +#if defined(NeXT) + /* third-party utilities can modify the default LUT exponent */ + LUT_exponent = 1.0 / 2.2; + /* + if (some_next_function_that_returns_gamma(&next_gamma)) + LUT_exponent = 1.0 / next_gamma; + */ +#elif defined(sgi) + LUT_exponent = 1.0 / 1.7; + /* there doesn't seem to be any documented function to + * get the "gamma" value, so we do it the hard way */ + tmpfile = fopen("/etc/config/system.glGammaVal", "r"); + if (tmpfile) { + double sgi_gamma; + + fgets(tmpline, 80, tmpfile); + fclose(tmpfile); + sgi_gamma = atof(tmpline); + if (sgi_gamma > 0.0) + LUT_exponent = 1.0 / sgi_gamma; + } +#elif defined(Macintosh) + LUT_exponent = 1.8 / 2.61; + /* + if (some_mac_function_that_returns_gamma(&mac_gamma)) + LUT_exponent = mac_gamma / 2.61; + */ +#else + LUT_exponent = 1.0; /* assume no LUT: most PCs */ +#endif + + /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ + default_display_exponent = LUT_exponent * CRT_exponent; + + + /* If the user has set the SCREEN_GAMMA environment variable as suggested + * (somewhat imprecisely) in the libpng documentation, use that; otherwise + * use the default value we just calculated. Either way, the user may + * override this via a command-line option. */ + + if ((p = getenv("SCREEN_GAMMA")) != NULL) { + double exponent = atof(p); + + if (exponent > 0.0) + default_gamma = 1.0 / exponent; + } + + if (default_gamma == 0.0) + default_gamma = 1.0 / default_display_exponent; + + + /* Now parse the command line for options and the PNM filename. */ + + while (*++argv && !error) { + if (!strncmp(*argv, "-i", 2)) { + wpng_info.interlaced = TRUE; + } else if (!strncmp(*argv, "-time", 3)) { + wpng_info.modtime = time(NULL); + wpng_info.have_time = TRUE; + } else if (!strncmp(*argv, "-text", 3)) { + text = TRUE; + } else if (!strncmp(*argv, "-gamma", 2)) { + if (!*++argv) + ++error; + else { + wpng_info.gamma = atof(*argv); + if (wpng_info.gamma <= 0.0) + ++error; + else if (wpng_info.gamma > 1.01) + fprintf(stderr, PROGNAME + " warning: file gammas are usually less than 1.0\n"); + } + } else if (!strncmp(*argv, "-bgcolor", 4)) { + if (!*++argv) + ++error; + else { + bgstr = *argv; + if (strlen(bgstr) != 7 || bgstr[0] != '#') + ++error; + else { + unsigned r, g, b; /* this way quiets compiler warnings */ + + sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); + wpng_info.bg_red = (uch)r; + wpng_info.bg_green = (uch)g; + wpng_info.bg_blue = (uch)b; + wpng_info.have_bg = TRUE; + } + } + } else { + if (**argv != '-') { + inname = *argv; + if (argv[1]) /* shouldn't be any more args after filename */ + ++error; + } else + ++error; /* not expecting any other options */ + } + } + + + /* open the input and output files, or register an error and abort */ + + if (!inname) { + if (isatty(0)) { + fprintf(stderr, PROGNAME + ": must give input filename or provide image data via stdin\n"); + ++error; + } else { +#ifdef DOS_OS2_W32 + /* some buggy C libraries require BOTH setmode() and fdopen(bin) */ + setmode(fileno(stdin), O_BINARY); + setmode(fileno(stdout), O_BINARY); +#endif + if ((wpng_info.infile = fdopen(fileno(stdin), "rb")) == NULL) { + fprintf(stderr, PROGNAME + ": unable to reopen stdin in binary mode\n"); + ++error; + } else + if ((wpng_info.outfile = fdopen(fileno(stdout), "wb")) == NULL) { + fprintf(stderr, PROGNAME + ": unable to reopen stdout in binary mode\n"); + fclose(wpng_info.infile); + ++error; + } else + wpng_info.filter = TRUE; + } + } else if ((len = strlen(inname)) > 250) { + fprintf(stderr, PROGNAME ": input filename is too long [%d chars]\n", + len); + ++error; + } else if (!(wpng_info.infile = fopen(inname, "rb"))) { + fprintf(stderr, PROGNAME ": can't open input file [%s]\n", inname); + ++error; + } + + if (!error) { + fgets(pnmline, 256, wpng_info.infile); + if (pnmline[0] != 'P' || ((pnmchar = pnmline[1]) != '5' && + pnmchar != '6' && pnmchar != '8')) + { + fprintf(stderr, PROGNAME + ": input file [%s] is not a binary PGM, PPM or PAM file\n", + inname); + ++error; + } else { + wpng_info.pnmtype = (int)(pnmchar - '0'); + if (wpng_info.pnmtype != 8) + wpng_info.have_bg = FALSE; /* no need for bg if opaque */ + do { + fgets(pnmline, 256, wpng_info.infile); /* lose any comments */ + } while (pnmline[0] == '#'); + sscanf(pnmline, "%ld %ld", &wpng_info.width, &wpng_info.height); + do { + fgets(pnmline, 256, wpng_info.infile); /* more comment lines */ + } while (pnmline[0] == '#'); + sscanf(pnmline, "%d", &maxval); + if (wpng_info.width <= 0L || wpng_info.height <= 0L || + maxval != 255) + { + fprintf(stderr, PROGNAME + ": only positive width/height, maxval == 255 allowed \n"); + ++error; + } + wpng_info.sample_depth = 8; /* <==> maxval 255 */ + + if (!wpng_info.filter) { + /* make outname from inname */ + if ((p = strrchr(inname, '.')) == NULL || + (p - inname) != (len - 4)) + { + strcpy(outname, inname); + strcpy(outname+len, ".png"); + } else { + len -= 4; + strncpy(outname, inname, len); + strcpy(outname+len, ".png"); + } + /* check if outname already exists; if not, open */ + if ((wpng_info.outfile = fopen(outname, "rb")) != NULL) { + fprintf(stderr, PROGNAME ": output file exists [%s]\n", + outname); + fclose(wpng_info.outfile); + ++error; + } else if (!(wpng_info.outfile = fopen(outname, "wb"))) { + fprintf(stderr, PROGNAME ": can't open output file [%s]\n", + outname); + ++error; + } + } + } + if (error) { + fclose(wpng_info.infile); + wpng_info.infile = NULL; + if (wpng_info.filter) { + fclose(wpng_info.outfile); + wpng_info.outfile = NULL; + } + } + } + + + /* if we had any errors, print usage and die horrible death...arrr! */ + + if (error) { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, APPNAME); + writepng_version_info(); + fprintf(stderr, "\n" +"Usage: %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] pnmfile\n" +"or: ... | %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] | ...\n" + " exp \ttransfer-function exponent (``gamma'') of the image in\n" + "\t\t floating-point format (e.g., ``%.5f''); if image looks\n" + "\t\t correct on given display system, image gamma is equal to\n" + "\t\t inverse of display-system exponent, i.e., 1 / (LUT * CRT)\n" + "\t\t (where LUT = lookup-table exponent and CRT = CRT exponent;\n" + "\t\t first varies, second is usually 2.2, all are positive)\n" + " bg \tdesired background color for alpha-channel images, in\n" + "\t\t 7-character hex RGB format (e.g., ``#ff7700'' for orange:\n" + "\t\t same as HTML colors)\n" + " -text\tprompt interactively for text info (tEXt chunks)\n" + " -time\tinclude a tIME chunk (last modification time)\n" + " -interlace\twrite interlaced PNG image\n" + "\n" +"pnmfile or stdin must be a binary PGM (`P5'), PPM (`P6') or (extremely\n" +"unofficial and unsupported!) PAM (`P8') file. Currently it is required\n" +"to have maxval == 255 (i.e., no scaling). If pnmfile is specified, it\n" +"is converted to the corresponding PNG file with the same base name but a\n" +"``.png'' extension; files read from stdin are converted and sent to stdout.\n" +"The conversion is progressive (low memory usage) unless interlacing is\n" +"requested; in that case the whole image will be buffered in memory and\n" +"written in one call.\n" + "\n", PROGNAME, PROGNAME, default_gamma); + exit(1); + } + + + /* prepare the text buffers for libpng's use; note that even though + * PNG's png_text struct includes a length field, we don't have to fill + * it out */ + + if (text && +#ifndef DOS_OS2_W32 + (keybd = fdopen(fileno(stderr), "r")) != NULL && +#endif + (textbuf = (char *)malloc((5 + 9)*75)) != NULL) + { + int i, valid, result; + + fprintf(stderr, + "Enter text info (no more than 72 characters per line);\n"); + fprintf(stderr, "to skip a field, hit the key.\n"); + /* note: just leaves len == 1 */ + + do { + valid = TRUE; + p = textbuf + TEXT_TITLE_OFFSET; + fprintf(stderr, " Title: "); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) { + if (p[len-1] == '\n') + p[--len] = '\0'; + wpng_info.title = p; + wpng_info.have_text |= TEXT_TITLE; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_TITLE; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_TITLE; + valid = FALSE; + } +#endif + } + } + } while (!valid); + + do { + valid = TRUE; + p = textbuf + TEXT_AUTHOR_OFFSET; + fprintf(stderr, " Author: "); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) { + if (p[len-1] == '\n') + p[--len] = '\0'; + wpng_info.author = p; + wpng_info.have_text |= TEXT_AUTHOR; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_AUTHOR; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_AUTHOR; + valid = FALSE; + } +#endif + } + } + } while (!valid); + + do { + valid = TRUE; + p = textbuf + TEXT_DESC_OFFSET; + fprintf(stderr, " Description (up to 9 lines):\n"); + for (i = 1; i < 10; ++i) { + fprintf(stderr, " [%d] ", i); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) + p += len; /* now points at NULL; char before is newline */ + else + break; + } + if ((len = p - (textbuf + TEXT_DESC_OFFSET)) > 1) { + if (p[-1] == '\n') { + p[-1] = '\0'; + --len; + } + wpng_info.desc = textbuf + TEXT_DESC_OFFSET; + wpng_info.have_text |= TEXT_DESC; + p = textbuf + TEXT_DESC_OFFSET; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_DESC; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_DESC; + valid = FALSE; + } +#endif + } + } + } while (!valid); + + do { + valid = TRUE; + p = textbuf + TEXT_COPY_OFFSET; + fprintf(stderr, " Copyright: "); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) { + if (p[len-1] == '\n') + p[--len] = '\0'; + wpng_info.copyright = p; + wpng_info.have_text |= TEXT_COPY; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_COPY; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_COPY; + valid = FALSE; + } +#endif + } + } + } while (!valid); + + do { + valid = TRUE; + p = textbuf + TEXT_EMAIL_OFFSET; + fprintf(stderr, " E-mail: "); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) { + if (p[len-1] == '\n') + p[--len] = '\0'; + wpng_info.email = p; + wpng_info.have_text |= TEXT_EMAIL; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_EMAIL; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_EMAIL; + valid = FALSE; + } +#endif + } + } + } while (!valid); + + do { + valid = TRUE; + p = textbuf + TEXT_URL_OFFSET; + fprintf(stderr, " URL: "); + fflush(stderr); + if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) { + if (p[len-1] == '\n') + p[--len] = '\0'; + wpng_info.url = p; + wpng_info.have_text |= TEXT_URL; + if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) { + fprintf(stderr, " " PROGNAME " warning: character code" + " %u is %sdiscouraged by the PNG\n specification " + "[first occurrence was at character position #%d]\n", + (unsigned)p[result], (p[result] == 27)? "strongly " : "", + result+1); + fflush(stderr); +#ifdef FORBID_LATIN1_CTRL + wpng_info.have_text &= ~TEXT_URL; + valid = FALSE; +#else + if (p[result] == 27) { /* escape character */ + wpng_info.have_text &= ~TEXT_URL; + valid = FALSE; + } +#endif + } + } + } while (!valid); + +#ifndef DOS_OS2_W32 + fclose(keybd); +#endif + + } else if (text) { + fprintf(stderr, PROGNAME ": unable to allocate memory for text\n"); + text = FALSE; + wpng_info.have_text = 0; + } + + + /* allocate libpng stuff, initialize transformations, write pre-IDAT data */ + + if ((rc = writepng_init(&wpng_info)) != 0) { + switch (rc) { + case 2: + fprintf(stderr, PROGNAME + ": libpng initialization problem (longjmp)\n"); + break; + case 4: + fprintf(stderr, PROGNAME ": insufficient memory\n"); + break; + case 11: + fprintf(stderr, PROGNAME + ": internal logic error (unexpected PNM type)\n"); + break; + default: + fprintf(stderr, PROGNAME + ": unknown writepng_init() error\n"); + break; + } + exit(rc); + } + + + /* free textbuf, since it's a completely local variable and all text info + * has just been written to the PNG file */ + + if (text && textbuf) { + free(textbuf); + textbuf = NULL; + } + + + /* calculate rowbytes on basis of image type; note that this becomes much + * more complicated if we choose to support PBM type, ASCII PNM types, or + * 16-bit-per-sample binary data [currently not an official NetPBM type] */ + + if (wpng_info.pnmtype == 5) + rowbytes = wpng_info.width; + else if (wpng_info.pnmtype == 6) + rowbytes = wpng_info.width * 3; + else /* if (wpng_info.pnmtype == 8) */ + rowbytes = wpng_info.width * 4; + + + /* read and write the image, either in its entirety (if writing interlaced + * PNG) or row by row (if non-interlaced) */ + + fprintf(stderr, "Encoding image data...\n"); + fflush(stderr); + + if (wpng_info.interlaced) { + long i; + ulg bytes; + ulg image_bytes = rowbytes * wpng_info.height; /* overflow? */ + + wpng_info.image_data = (uch *)malloc(image_bytes); + wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *)); + if (wpng_info.image_data == NULL || wpng_info.row_pointers == NULL) { + fprintf(stderr, PROGNAME ": insufficient memory for image data\n"); + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(5); + } + for (i = 0; i < wpng_info.height; ++i) + wpng_info.row_pointers[i] = wpng_info.image_data + i*rowbytes; + bytes = fread(wpng_info.image_data, 1, image_bytes, wpng_info.infile); + if (bytes != image_bytes) { + fprintf(stderr, PROGNAME ": expected %lu bytes, got %lu bytes\n", + image_bytes, bytes); + fprintf(stderr, " (continuing anyway)\n"); + } + if (writepng_encode_image(&wpng_info) != 0) { + fprintf(stderr, PROGNAME + ": libpng problem (longjmp) while writing image data\n"); + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(2); + } + + } else /* not interlaced: write progressively (row by row) */ { + long j; + ulg bytes; + + wpng_info.image_data = (uch *)malloc(rowbytes); + if (wpng_info.image_data == NULL) { + fprintf(stderr, PROGNAME ": insufficient memory for row data\n"); + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(5); + } + error = 0; + for (j = wpng_info.height; j > 0L; --j) { + bytes = fread(wpng_info.image_data, 1, rowbytes, wpng_info.infile); + if (bytes != rowbytes) { + fprintf(stderr, PROGNAME + ": expected %lu bytes, got %lu bytes (row %ld)\n", rowbytes, + bytes, wpng_info.height-j); + ++error; + break; + } + if (writepng_encode_row(&wpng_info) != 0) { + fprintf(stderr, PROGNAME + ": libpng problem (longjmp) while writing row %ld\n", + wpng_info.height-j); + ++error; + break; + } + } + if (error) { + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(2); + } + if (writepng_encode_finish(&wpng_info) != 0) { + fprintf(stderr, PROGNAME ": error on final libpng call\n"); + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(2); + } + } + + + /* OK, we're done (successfully): clean up all resources and quit */ + + fprintf(stderr, "Done.\n"); + fflush(stderr); + + writepng_cleanup(&wpng_info); + wpng_cleanup(); + + return 0; +} + + + + + +static int wpng_isvalid_latin1(uch *p, int len) +{ + int i, result = -1; + + for (i = 0; i < len; ++i) { + if (p[i] == 10 || (p[i] > 31 && p[i] < 127) || p[i] > 160) + continue; /* character is completely OK */ + if (result < 0 || (p[result] != 27 && p[i] == 27)) + result = i; /* mark location of first questionable one */ + } /* or of first escape character (bad) */ + + return result; +} + + + + + +static void wpng_cleanup(void) +{ + if (wpng_info.outfile) { + fclose(wpng_info.outfile); + wpng_info.outfile = NULL; + } + + if (wpng_info.infile) { + fclose(wpng_info.infile); + wpng_info.infile = NULL; + } + + if (wpng_info.image_data) { + free(wpng_info.image_data); + wpng_info.image_data = NULL; + } + + if (wpng_info.row_pointers) { + free(wpng_info.row_pointers); + wpng_info.row_pointers = NULL; + } +} + + + + +#ifdef DOS_OS2_W32 + +static char *dos_kbd_gets(char *buf, int len) +{ + int ch, count=0; + + do { + buf[count++] = ch = getche(); + } while (ch != '\r' && count < len-1); + + buf[count--] = '\0'; /* terminate string */ + if (buf[count] == '\r') /* Enter key makes CR, so change to newline */ + buf[count] = '\n'; + + fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */ + fflush(stderr); + + return buf; +} + +#endif /* DOS_OS2_W32 */ diff --git a/extern/libpng/include/contrib/gregbook/writepng.c b/extern/libpng/include/contrib/gregbook/writepng.c new file mode 100644 index 0000000000..f07f4a8a02 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/writepng.c @@ -0,0 +1,400 @@ +/*--------------------------------------------------------------------------- + + wpng - simple PNG-writing program writepng.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + + +#include /* for exit() prototype */ + +#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include "writepng.h" /* typedefs, common macros, public prototypes */ + + +/* local prototype */ + +static void writepng_error_handler(png_structp png_ptr, png_const_charp msg); + + + +void writepng_version_info(void) +{ + fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver); + fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", + ZLIB_VERSION, zlib_version); +} + + + + +/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for + * unexpected pnmtype; note that outfile might be stdout */ + +int writepng_init(mainprog_info *mainprog_ptr) +{ + png_structp png_ptr; /* note: temporary variables! */ + png_infop info_ptr; + int color_type, interlace_type; + + + /* could also replace libpng warning-handler (final NULL), but no need: */ + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, + writepng_error_handler, NULL); + if (!png_ptr) + return 4; /* out of memory */ + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + return 4; /* out of memory */ + } + + + /* setjmp() must be called in every function that calls a PNG-writing + * libpng function, unless an alternate error handler was installed-- + * but compatible error handlers must either use longjmp() themselves + * (as in this program) or some other method to return control to + * application code, so here we go: */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + return 2; + } + + + /* make sure outfile is (re)opened in BINARY mode */ + + png_init_io(png_ptr, mainprog_ptr->outfile); + + + /* set the compression levels--in general, always want to leave filtering + * turned on (except for palette images) and allow all of the filters, + * which is the default; want 32K zlib window, unless entire image buffer + * is 16K or smaller (unknown here)--also the default; usually want max + * compression (NOT the default); and remaining compression flags should + * be left alone */ + + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); +/* + >> this is default for no filtering; Z_FILTERED is default otherwise: + png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); + >> these are all defaults: + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + */ + + + /* set the image parameters appropriately */ + + if (mainprog_ptr->pnmtype == 5) + color_type = PNG_COLOR_TYPE_GRAY; + else if (mainprog_ptr->pnmtype == 6) + color_type = PNG_COLOR_TYPE_RGB; + else if (mainprog_ptr->pnmtype == 8) + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else { + png_destroy_write_struct(&png_ptr, &info_ptr); + return 11; + } + + interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 : + PNG_INTERLACE_NONE; + + png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height, + mainprog_ptr->sample_depth, color_type, interlace_type, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + if (mainprog_ptr->gamma > 0.0) + png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma); + + if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */ + png_color_16 background; + + background.red = mainprog_ptr->bg_red; + background.green = mainprog_ptr->bg_green; + background.blue = mainprog_ptr->bg_blue; + png_set_bKGD(png_ptr, info_ptr, &background); + } + + if (mainprog_ptr->have_time) { + png_time modtime; + + png_convert_from_time_t(&modtime, mainprog_ptr->modtime); + png_set_tIME(png_ptr, info_ptr, &modtime); + } + + if (mainprog_ptr->have_text) { + png_text text[6]; + int num_text = 0; + + if (mainprog_ptr->have_text & TEXT_TITLE) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "Title"; + text[num_text].text = mainprog_ptr->title; + ++num_text; + } + if (mainprog_ptr->have_text & TEXT_AUTHOR) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "Author"; + text[num_text].text = mainprog_ptr->author; + ++num_text; + } + if (mainprog_ptr->have_text & TEXT_DESC) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "Description"; + text[num_text].text = mainprog_ptr->desc; + ++num_text; + } + if (mainprog_ptr->have_text & TEXT_COPY) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "Copyright"; + text[num_text].text = mainprog_ptr->copyright; + ++num_text; + } + if (mainprog_ptr->have_text & TEXT_EMAIL) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "E-mail"; + text[num_text].text = mainprog_ptr->email; + ++num_text; + } + if (mainprog_ptr->have_text & TEXT_URL) { + text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + text[num_text].key = "URL"; + text[num_text].text = mainprog_ptr->url; + ++num_text; + } + png_set_text(png_ptr, info_ptr, text, num_text); + } + + + /* write all chunks up to (but not including) first IDAT */ + + png_write_info(png_ptr, info_ptr); + + + /* if we wanted to write any more text info *after* the image data, we + * would set up text struct(s) here and call png_set_text() again, with + * just the new data; png_set_tIME() could also go here, but it would + * have no effect since we already called it above (only one tIME chunk + * allowed) */ + + + /* set up the transformations: for now, just pack low-bit-depth pixels + * into bytes (one, two or four pixels per byte) */ + + png_set_packing(png_ptr); +/* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */ + + + /* make sure we save our pointers for use in writepng_encode_image() */ + + mainprog_ptr->png_ptr = png_ptr; + mainprog_ptr->info_ptr = info_ptr; + + + /* OK, that's all we need to do for now; return happy */ + + return 0; +} + + + + + +/* returns 0 for success, 2 for libpng (longjmp) problem */ + +int writepng_encode_image(mainprog_info *mainprog_ptr) +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + + /* as always, setjmp() must be called in every function that calls a + * PNG-writing libpng function */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + mainprog_ptr->png_ptr = NULL; + mainprog_ptr->info_ptr = NULL; + return 2; + } + + + /* and now we just write the whole image; libpng takes care of interlacing + * for us */ + + png_write_image(png_ptr, mainprog_ptr->row_pointers); + + + /* since that's it, we also close out the end of the PNG file now--if we + * had any text or time info to write after the IDATs, second argument + * would be info_ptr, but we optimize slightly by sending NULL pointer: */ + + png_write_end(png_ptr, NULL); + + return 0; +} + + + + + +/* returns 0 if succeeds, 2 if libpng problem */ + +int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */ +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + + /* as always, setjmp() must be called in every function that calls a + * PNG-writing libpng function */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + mainprog_ptr->png_ptr = NULL; + mainprog_ptr->info_ptr = NULL; + return 2; + } + + + /* image_data points at our one row of image data */ + + png_write_row(png_ptr, mainprog_ptr->image_data); + + return 0; +} + + + + + +/* returns 0 if succeeds, 2 if libpng problem */ + +int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */ +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + + /* as always, setjmp() must be called in every function that calls a + * PNG-writing libpng function */ + + if (setjmp(mainprog_ptr->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + mainprog_ptr->png_ptr = NULL; + mainprog_ptr->info_ptr = NULL; + return 2; + } + + + /* close out PNG file; if we had any text or time info to write after + * the IDATs, second argument would be info_ptr: */ + + png_write_end(png_ptr, NULL); + + return 0; +} + + + + + +void writepng_cleanup(mainprog_info *mainprog_ptr) +{ + png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; + png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; + + if (png_ptr && info_ptr) + png_destroy_write_struct(&png_ptr, &info_ptr); +} + + + + + +static void writepng_error_handler(png_structp png_ptr, png_const_charp msg) +{ + mainprog_info *mainprog_ptr; + + /* This function, aside from the extra step of retrieving the "error + * pointer" (below) and the fact that it exists within the application + * rather than within libpng, is essentially identical to libpng's + * default error handler. The second point is critical: since both + * setjmp() and longjmp() are called from the same code, they are + * guaranteed to have compatible notions of how big a jmp_buf is, + * regardless of whether _BSD_SOURCE or anything else has (or has not) + * been defined. */ + + fprintf(stderr, "writepng libpng error: %s\n", msg); + fflush(stderr); + + mainprog_ptr = png_get_error_ptr(png_ptr); + if (mainprog_ptr == NULL) { /* we are completely hosed now */ + fprintf(stderr, + "writepng severe error: jmpbuf not recoverable; terminating.\n"); + fflush(stderr); + exit(99); + } + + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ + longjmp(mainprog_ptr->jmpbuf, 1); +} diff --git a/extern/libpng/include/contrib/gregbook/writepng.h b/extern/libpng/include/contrib/gregbook/writepng.h new file mode 100644 index 0000000000..78b966b587 --- /dev/null +++ b/extern/libpng/include/contrib/gregbook/writepng.h @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------- + + wpng - simple PNG-writing program writepng.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + + This software is provided "as is," without warranty of any kind, + express or implied. In no event shall the author or contributors + be held liable for any damages arising in any way from the use of + this software. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. Redistributions of source code must retain the above copyright + notice, disclaimer, and this list of conditions. + 2. Redistributions in binary form must reproduce the above copyright + notice, disclaimer, and this list of conditions in the documenta- + tion and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + + This product includes software developed by Greg Roelofs + and contributors for the book, "PNG: The Definitive Guide," + published by O'Reilly and Associates. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b)? (a) : (b)) +# define MIN(a,b) ((a) < (b)? (a) : (b)) +#endif + +#ifdef DEBUG +# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} +#else +# define Trace(x) ; +#endif + +#define TEXT_TITLE 0x01 +#define TEXT_AUTHOR 0x02 +#define TEXT_DESC 0x04 +#define TEXT_COPY 0x08 +#define TEXT_EMAIL 0x10 +#define TEXT_URL 0x20 + +#define TEXT_TITLE_OFFSET 0 +#define TEXT_AUTHOR_OFFSET 72 +#define TEXT_COPY_OFFSET (2*72) +#define TEXT_EMAIL_OFFSET (3*72) +#define TEXT_URL_OFFSET (4*72) +#define TEXT_DESC_OFFSET (5*72) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +typedef struct _mainprog_info { + double gamma; + long width; + long height; + time_t modtime; + FILE *infile; + FILE *outfile; + void *png_ptr; + void *info_ptr; + uch *image_data; + uch **row_pointers; + char *title; + char *author; + char *desc; + char *copyright; + char *email; + char *url; + int filter; /* command-line-filter flag, not PNG row filter! */ + int pnmtype; + int sample_depth; + int interlaced; + int have_bg; + int have_time; + int have_text; + jmp_buf jmpbuf; + uch bg_red; + uch bg_green; + uch bg_blue; +} mainprog_info; + + +/* prototypes for public functions in writepng.c */ + +void writepng_version_info(void); + +int writepng_init(mainprog_info *mainprog_ptr); + +int writepng_encode_image(mainprog_info *mainprog_ptr); + +int writepng_encode_row(mainprog_info *mainprog_ptr); + +int writepng_encode_finish(mainprog_info *mainprog_ptr); + +void writepng_cleanup(mainprog_info *mainprog_ptr); diff --git a/extern/libpng/include/contrib/pngminim/README b/extern/libpng/include/contrib/pngminim/README new file mode 100644 index 0000000000..51d5a3c230 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/README @@ -0,0 +1,4 @@ +This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa +to build minimal decoder, encoder, and progressive reader applications. + +See the individual README and pngusr.dfa files for more explanation. diff --git a/extern/libpng/include/contrib/pngminim/decoder/README b/extern/libpng/include/contrib/pngminim/decoder/README new file mode 100644 index 0000000000..5618cb78aa --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/decoder/README @@ -0,0 +1,10 @@ +This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa + +The makefile builds a minimal read-only decoder with embedded libpng +and zlib. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +If you prefer to use the shared libraries, go to contrib/pngminus +and build the png2pnm application there. diff --git a/extern/libpng/include/contrib/pngminim/decoder/makefile b/extern/libpng/include/contrib/pngminim/decoder/makefile new file mode 100644 index 0000000000..e10e1225d6 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/decoder/makefile @@ -0,0 +1,150 @@ +# Makefile for PngMinus (pngm2pnm) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) + +# If awk fails try +# make AWK=nawk + +# If cpp fails try +# make CPP=/lib/cpp + +RM=rm -f +COPY=cp + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/pngminus + +# Zlib (minimal inflate requirements - crc32 is used by libpng) +# zutil can be eliminated if you provide your own zcalloc and zcfree +ZSRCS = adler32$(C) crc32$(C) \ + inffast$(C) inflate$(C) inftrees$(C) \ + zutil$(C) + +# Standard headers +ZH = zlib.h crc32.h inffast.h inffixed.h \ + inflate.h inftrees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +ZOBJS = adler32$(O) crc32$(O) \ + inffast$(O) inflate$(O) inftrees$(O) \ + zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \ + pngset$(C) pngtrans$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \ + pngset$(O) pngtrans$(O) + +PROGSRCS= pngm2pnm$(C) +PROGHDRS= +PROGDOCS= +PROGOBJS= pngm2pnm$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +# note: dependencies do not work on implicit rule lines +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: pngm2pnm$(E) + +pngm2pnm$(E): $(OBJS) + $(LD) -o pngm2pnm$(E) $(OBJS) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) pngm2pnm$(O) + $(RM) pngm2pnm$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +pngm2pnm.c: $(PROGSRC)/png2pnm.c + $(RM) $@ + $(COPY) $(PROGSRC)/png2pnm.c $@ + +# End of makefile for pngm2pnm diff --git a/extern/libpng/include/contrib/pngminim/decoder/pngusr.dfa b/extern/libpng/include/contrib/pngminim/decoder/pngusr.dfa new file mode 100644 index 0000000000..9653cd1862 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/decoder/pngusr.dfa @@ -0,0 +1,39 @@ +# pngminim/decoder/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# All that is required is some read code. This example switches +# on the sequential read code (see ../preader for a progressive +# read example). + +option SEQUENTIAL_READ on + +# You must choose fixed or floating point arithmetic: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): +# option FLOATING_ARITHMETIC on + +option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, pngm2pnm, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on +option READ_EXPAND on +option READ_16_TO_8 on diff --git a/extern/libpng/include/contrib/pngminim/decoder/pngusr.h b/extern/libpng/include/contrib/pngminim/decoder/pngusr.h new file mode 100644 index 0000000000..ce85537528 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/decoder/pngusr.h @@ -0,0 +1,23 @@ +/* minrdpngconf.h: headers to make a minimal png-read-only library + * + * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINRDPNGCONF_H +#define MINRDPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINRDPNGCONF_H */ diff --git a/extern/libpng/include/contrib/pngminim/encoder/README b/extern/libpng/include/contrib/pngminim/encoder/README new file mode 100644 index 0000000000..04fd27f44f --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/encoder/README @@ -0,0 +1,10 @@ +This demonstrates the use of PNG_USER_CONFIG and pngusr.h + +The makefile builds a minimal write-only decoder with embedded libpng +and zlib. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +If you prefer to use the shared libraries, go to contrib/pngminus +and build the pnm2png application there. diff --git a/extern/libpng/include/contrib/pngminim/encoder/makefile b/extern/libpng/include/contrib/pngminim/encoder/makefile new file mode 100644 index 0000000000..d6f39e2ea0 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/encoder/makefile @@ -0,0 +1,149 @@ +# Makefile for PngMinus (pnm2pngm) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) + +# If awk fails try +# make AWK=nawk + +# If cpp fails try +# make CPP=/lib/cpp + +RM=rm -f +COPY=cp + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZIP -I. -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/pngminus + +# Zlib +ZSRCS = adler32$(C) compress$(C) crc32$(C) deflate$(C) \ + trees$(C) zutil$(C) + +# Standard headers +#ZH = zlib.h crc32.h deflate.h trees.h zutil.h +ZH = zlib.h crc32.h deflate.h trees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +# compress is not required; it is needed to link the zlib +# code because deflate defines an unused API function deflateBound +# which itself calls compressBound from compress. +ZOBJS = adler32$(O) compress$(O) crc32$(O) deflate$(O) \ + trees$(O) zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngset$(C) pngtrans$(C) pngwio$(C) pngwrite$(C) \ + pngwtran$(C) pngwutil$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngset$(O) pngtrans$(O) pngwio$(O) pngwrite$(O) \ + pngwtran$(O) pngwutil$(O) + +PROGSRCS= pnm2pngm$(C) +PROGHDRS= +PROGDOCS= +PROGOBJS= pnm2pngm$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: pnm2pngm$(E) + +pnm2pngm$(E): $(OBJS) + $(LD) -o pnm2pngm$(E) $(OBJS) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) pnm2pngm$(O) + $(RM) pnm2pngm$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +pnm2pngm.c: $(PROGSRC)/pnm2png.c + $(RM) $@ + $(COPY) $(PROGSRC)/pnm2png.c $@ + +# End of makefile for pnm2pngm diff --git a/extern/libpng/include/contrib/pngminim/encoder/pngusr.dfa b/extern/libpng/include/contrib/pngminim/encoder/pngusr.dfa new file mode 100644 index 0000000000..ee88443c9d --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/encoder/pngusr.dfa @@ -0,0 +1,35 @@ +# pngminim/encoder/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# Switch on the write code - this makes a minimalist encoder + +option WRITE on + +# You must choose fixed or floating point arithmetic: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): +# option FLOATING_ARITHMETIC on + +option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, pnm2pngm, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on diff --git a/extern/libpng/include/contrib/pngminim/encoder/pngusr.h b/extern/libpng/include/contrib/pngminim/encoder/pngusr.h new file mode 100644 index 0000000000..fb35245ee5 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/encoder/pngusr.h @@ -0,0 +1,23 @@ +/* minwrpngconf.h: headers to make a minimal png-write-only library + * + * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINWRPNGCONF_H +#define MINWRPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINWRPNGCONF_H */ diff --git a/extern/libpng/include/contrib/pngminim/preader/README b/extern/libpng/include/contrib/pngminim/preader/README new file mode 100644 index 0000000000..6bf1db05c0 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/preader/README @@ -0,0 +1,15 @@ +This demonstrates the use of PNG_USER_CONFIG and pngusr.h + +The makefile builds a minimal read-only progressive decoder with +embedded libpng, zlib and your system's X library. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +Edit makefile if required, to find your X library and include files, +then + + make ZLIBSRC=directory + +If you prefer to use the shared libraries, go to contrib/gregbook +and build the rpng2-x application there. diff --git a/extern/libpng/include/contrib/pngminim/preader/makefile b/extern/libpng/include/contrib/pngminim/preader/makefile new file mode 100644 index 0000000000..f4b0ccdc8a --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/preader/makefile @@ -0,0 +1,165 @@ +# Makefile for PngMinus (rpng2) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) + +# If awk fails try +# make AWK=nawk + +# If cpp fails try +# make CPP=/lib/cpp + +RM=rm -f +COPY=cp + +#XINC = -I/usr/include # old-style, stock X distributions +#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX) + +#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 + +XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.) +XLIB = -L/usr/X11R6/lib -lX11 +#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64 + +#XINC = -I/usr/local/include # FreeBSD +#XLIB = -L/usr/local/lib -lX11 + +#LIBS = $(XLIB) +LIBS = $(XLIB) -lm #platforms that need libm + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. $(XINC) -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/gregbook + +# Zlib (minimal inflate requirements - crc32 is used by libpng) +# zutil can be eliminated if you provide your own zcalloc and zcfree +ZSRCS = adler32$(C) crc32$(C) \ + inffast$(C) inflate$(C) inftrees$(C) \ + zutil$(C) + +# Standard headers +ZH = zlib.h crc32.h inffast.h inffixed.h \ + inflate.h inftrees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +ZOBJS = adler32$(O) crc32$(O) \ + inffast$(O) inflate$(O) inftrees$(O) \ + zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngpread$(C) pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \ + pngset$(C) pngtrans$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngpread$(O) pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \ + pngset$(O) pngtrans$(O) + +PROGSRCS= rpng2-x$(C) readpng2$(C) +PROGHDRS= readpng2.h +PROGDOCS= COPYING LICENSE +PROGOBJS= rpng2-x$(O) readpng2$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: $(PROGDOCS) rpng2-x$(E) + +rpng2-x$(E): $(OBJS) + $(LD) -o rpng2-x$(E) $(OBJS) $(LIBS) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) rpng2-x$(O) + $(RM) rpng2-x$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +$(PROGSRCS) $(PROGHDRS) $(PROGDOCS): $(PROGSRC)/$@ + $(RM) $@ + $(COPY) $(PROGSRC)/$@ $@ + +# End of makefile for rpng2-x diff --git a/extern/libpng/include/contrib/pngminim/preader/pngusr.dfa b/extern/libpng/include/contrib/pngminim/preader/pngusr.dfa new file mode 100644 index 0000000000..5fa9c55bf2 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/preader/pngusr.dfa @@ -0,0 +1,40 @@ +# pngminim/preader/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# Just switch on the progressive read code + +option PROGRESSIVE_READ on + +# You may choose fixed or floating point APIs: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): + +option FLOATING_ARITHMETIC on +# option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, rpng2-x, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on +option READ_bKGD on +option READ_GAMMA on +option READ_EXPAND on +option READ_16_TO_8 on +option READ_GRAY_TO_RGB on diff --git a/extern/libpng/include/contrib/pngminim/preader/pngusr.h b/extern/libpng/include/contrib/pngminim/preader/pngusr.h new file mode 100644 index 0000000000..b40cc46ce6 --- /dev/null +++ b/extern/libpng/include/contrib/pngminim/preader/pngusr.h @@ -0,0 +1,23 @@ +/* minrdpngconf.h: headers to make a minimal png-read-only library + * + * Copyright (c) 2009, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINPRDPNGCONF_H +#define MINPRDPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINPRDPNGCONF_H */ diff --git a/extern/libpng/include/contrib/pngminus/README b/extern/libpng/include/contrib/pngminus/README new file mode 100644 index 0000000000..bbe7407ecc --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/README @@ -0,0 +1,153 @@ +PngMinus +-------- +(copyright Willem van Schaik, 1999) + + +License +------- + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation. This software is provided "as is" without +express or implied warranty. + + +Some history +------------ +Soon after the creation of PNG in 1995, the need was felt for a set of +pnmtopng / pngtopnm utilities. Independantly Alexander Lehmann and I +(Willem van Schaik) started such a project. Luckily we discovered this +and merged the two together into pnmtopng.tar.gz, which is available +from a/o ftp://ftp.simplesystems.org/pub/libpng/png/. + +These two utilities have many, many options and make use of most of the +features of PNG, like gamma, alpha, sbit, text-chunks, etc. This makes +the utilities quite complex and by now not anymore very maintainable. +When we wrote these programs, libpng was still in an early stage. +Therefore, lots of the functionality that we put in our software can now +be done using transform-functions in libpng. + +Finally, to compile these programs, you need to have installed and +compiled three libraries: libpng, zlib and netpbm. Especially the latter +makes the whole setup a bit bulky. But that's unavoidable given the many +features of pnmtopng. + + +What now +-------- +At this moment libpng is in a very stable state and can do much of the +work done in pnmtopng. Also, pnmtopng needs to be upgraded to the new +interface of libpng. Hence, it is time for a rewrite from the ground up +of pnmtopng and pngtopnm. This will happen in the near future (stay +tuned). The new package will get a different name to distinguish it from +the old one: PngPlus. + +To experiment a bit with the new interface of libpng, I started off with +a small prototype that contains only the basic functionality. It doesn't +have any of the options to read or write special chunks and it will do +no gamma correction. But this makes it also a simple program that is +quite easy to understand and can serve well as a template for other +software developments. (By now there are of course a couple of programs, +like Greg Roelofs' rpng/wpng, that can be used just as good.) + + +Can and can not +--------------- +As this is the small brother of the future PngPlus, I called this fellow +PngMinus. Because I started this development in good-old Turbo-C, I +avoided the use the netpbm library, which requires DOS extenders. Again, +another reason to call it PngMinus (minus netpbm :-). So, part of the +program are some elementary routines to read / write pgm- and ppm-files. +It does not read b&w pbm-files. + +The downside of this approach is that you can not use them on images +that require blocks of memory bigger than 64k (the DOS version). For +larger images you will get an out-of-memory error. + +As said before, PngMinus doesn't correct for gamma. When reading +png-files you can do this just as well by piping the output of png2pnm +to pnmgamma, one of the standard PbmPlus tools. This same scenario will +most probably also be followed in the full-blown future PngPlus, with +the addition of course of the possibility to create gamma-chunks when +writing png-files. + +On the other hand it supports alpha-channels. When reading a png-image +you can write the alpha-channel into a pgm-file. And when creating an +RGB+A png-image, you just combine a ppm-file with a corresponding +pgm-file containing the alpha-channel. When reading, transparency chunks +are converted into an alpha-channel and from there on treated the same +way. + +Finally you can opt for writing ascii or binary pgm- and ppm-files. When +the bit-depth is 16, the format will always be ascii. + + +Using it +-------- +To distinguish them from pnmtopng and PngPlus, the utilities are named +png2pnm and pnm2png (2 instead of to). The input- and output-files can +be given as parameters or through redirection. Therefore the programs +can be part of a pipe. + +To list the options type "png2pnm -h" or "pnm2png -h". + + +Just like Scandinavian furniture +-------------------------------- +You have to put it together yourself. I did test the software under +MS-DOS with Turbo-C 3.0 and under RedHat Linux 4.2 with gcc. In both +cases I used libpng-1.0.4 and zlib-1.1.3. Later versions should be OK, +however some older libpng versions have a bug in pngmem.c when using +Turbo-C 3.0 (see below). + +You can build it using one of the two makefiles (make -f makefile.###) +or use the batch/script files pngminus.bat / pngminus.sh. This assumes +that you have built the libraries in ../libpng and ../zlib. Using Linux, +make sure that you have built libpng with makefile.std and not +makefile.linux (also called .lnx in earlier versions of libpng). The +latter creates a .so shared-library, while the PngMinus makefile assumes +a normal .a static library. + +If you create a ../pngsuite directory and then store the basn####.png +files from PngSuite (http://www.schaik.com/pngsuite/) in there, you can +test in one go the proper functioning of PngMinus, see png2pnm.bat and +pnm2png.bat (or the .sh versions). + + +Warranty +------- +Please, remember that this was just a small experiment to learn a few +things. It will have many unforeseen features . Who said bugs? Use +it when you are in need for something simple or when you want to start +developing your own stuff. + + +The Turbo bug +------------- +** pngmem.old + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr += 16L; +** pngmem.c + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; +** + +** pngmem.old + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr += (png_uint_32)65536L; +** pngmem.c + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + 65536L; +** + + +The end +------- +Willem van Schaik +mailto:willem@schaik.com +http://www.schaik.com/png/ +------- +Oct 1999 + diff --git a/extern/libpng/include/contrib/pngminus/makefile.std b/extern/libpng/include/contrib/pngminus/makefile.std new file mode 100644 index 0000000000..2fb061bbe2 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/makefile.std @@ -0,0 +1,65 @@ +# Makefile for PngMinus (png2pnm and pnm2png) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) + +RM=rm -f + +#PNGPATH = /usr/local +#PNGINC = -I$(PNGPATH)/include/libpng12 +#PNGLIB = -L$(PNGPATH)/lib -lpng12 +#PNGLIBS = $(PNGPATH)/lib/libpng12.a +PNGINC = -I../.. +PNGLIB = -L../.. -lpng +PNGLIBS = ../../libpng.a + +#ZPATH = /usr/local +#ZINC = -I$(ZPATH)/include +#ZLIB = -L$(ZPATH)/lib -lz +#ZLIBS = $(ZPATH)/lib/libz.a +ZINC = -I../../../zlib +ZLIB = -L../../../zlib -lz +ZLIBS = ../../../zlib/libz.a + +CFLAGS=-O3 $(PNGINC) $(ZINC) +LDFLAGS=$(PNGLIB) $(ZLIB) +LDFLAGSS=$(PNGLIBS) $(ZLIBS) +C=.c +O=.o +L=.a +E= + +# dependencies + +#all: png2pnm$(E) pnm2png$(E) +all: png2pnm$(E) pnm2png$(E) png2pnm-static$(E) pnm2png-static$(E) + +png2pnm$(O): png2pnm$(C) + $(CC) -c $(CFLAGS) png2pnm$(C) + +png2pnm$(E): png2pnm$(O) + $(LD) -o png2pnm$(E) png2pnm$(O) $(LDFLAGS) -lm + +png2pnm-static$(E): png2pnm$(O) + $(LD) -o png2pnm-static$(E) png2pnm$(O) $(LDFLAGSS) -lm + +pnm2png$(O): pnm2png$(C) + $(CC) -c $(CFLAGS) pnm2png$(C) + +pnm2png$(E): pnm2png$(O) + $(LD) -o pnm2png$(E) pnm2png$(O) $(LDFLAGS) -lm + +pnm2png-static$(E): pnm2png$(O) + $(LD) -o pnm2png-static$(E) pnm2png$(O) $(LDFLAGSS) -lm + +clean: + $(RM) png2pnm$(O) + $(RM) pnm2png$(O) + $(RM) png2pnm$(E) + $(RM) pnm2png$(E) + $(RM) png2pnm-static$(E) + $(RM) pnm2png-static$(E) + +# End of makefile for png2pnm / pnm2png diff --git a/extern/libpng/include/contrib/pngminus/makefile.tc3 b/extern/libpng/include/contrib/pngminus/makefile.tc3 new file mode 100644 index 0000000000..404f18d5b1 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/makefile.tc3 @@ -0,0 +1,38 @@ +# Makefile for PngMinus (png2pnm and pnm2png) +# TurboC++ 3.0 + +CC=tcc -Ic:\tc3\inc +LD=tcc -Lc:\tc3\lib +LB=tlib +RM=del +CP=copy +MODEL=l +CCFLAGS=-O -m$(MODEL) -I..\libpng -I..\zlib +LDFLAGS=-m$(MODEL) -L..\libpng -L..\zlib +C=.c +O=.obj +L=.lib +E=.exe + +# dependencies + +all: png2pnm$(E) pnm2png$(E) + +png2pnm$(O): png2pnm$(C) + $(CC) -c $(CCFLAGS) png2pnm$(C) + +png2pnm$(E): png2pnm$(O) + $(LD) $(LDFLAGS) png2pnm$(O) libpng$(L) zlib$(L) + +pnm2png$(O): pnm2png$(C) + $(CC) -c $(CCFLAGS) pnm2png$(C) + +pnm2png$(E): pnm2png$(O) + $(LD) $(LDFLAGS) pnm2png$(O) libpng$(L) zlib$(L) + +clean: + $(RM) *$(O) + $(RM) *$(E) + +# End of makefile for png2pnm / pnm2png + diff --git a/extern/libpng/include/contrib/pngminus/makevms.com b/extern/libpng/include/contrib/pngminus/makevms.com new file mode 100644 index 0000000000..00561bcd0d --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/makevms.com @@ -0,0 +1,92 @@ +$!------------------------------------------------------------------------------ +$! make Contrib programs of libpng under OpenVMS +$! +$! +$! Look for the compiler used +$! +$ zlibsrc = "[---.zlib]" +$ ccopt="/include=(''zlibsrc',[--])" +$ if f$getsyi("HW_MODEL").ge.1024 +$ then +$ ccopt = "/prefix=all"+ccopt +$ comp = "__decc__=1" +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ else +$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" +$ then +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs."" +$ then +$ comp = "__gcc__=1" +$ CC :== GCC +$ else +$ comp = "__vaxc__=1" +$ endif +$ else +$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include: +$ ccopt = "/decc/prefix=all"+ccopt +$ comp = "__decc__=1" +$ endif +$ endif +$ open/write lopt lib.opt +$ write lopt "[--]libpng.olb/lib" +$ write lopt "''zlibsrc'libz.olb/lib" +$ close lopt +$ open/write xopt x11.opt +$ write xopt "sys$library:decw$xlibshr.exe/share" +$ close xopt +$ write sys$output "Compiling PNG contrib programs ..." +$ write sys$output "Building pnm2png..." +$ CALL MAKE pnm2png.OBJ "cc ''CCOPT' pnm2png" - + pnm2png.c +$ call make pnm2png.exe - + "LINK pnm2png,lib.opt/opt" - + pnm2png.obj +$ write sys$output "Building png2pnm..." +$ CALL MAKE png2pnm.OBJ "cc ''CCOPT' png2pnm" - + png2pnm.c +$ call make png2pnm.exe - + "LINK png2pnm,lib.opt/opt" - + png2pnm.obj +$ exit +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE diff --git a/extern/libpng/include/contrib/pngminus/png2pnm.bat b/extern/libpng/include/contrib/pngminus/png2pnm.bat new file mode 100644 index 0000000000..449cf36750 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/png2pnm.bat @@ -0,0 +1,41 @@ +REM -- grayscale +png2pnm.exe -noraw ..\pngsuite\basn0g01.png basn0g01.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g02.png basn0g02.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g04.png basn0g04.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g08.png basn0g08.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g16.png basn0g16.pgm +REM -- full-color +png2pnm.exe -noraw ..\pngsuite\basn2c08.png basn2c08.ppm +png2pnm.exe -noraw ..\pngsuite\basn2c16.png basn2c16.ppm +REM -- palletted +png2pnm.exe -noraw ..\pngsuite\basn3p01.png basn3p01.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p02.png basn3p02.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p04.png basn3p04.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p08.png basn3p08.ppm +REM -- gray with alpha-channel +png2pnm.exe -noraw ..\pngsuite\basn4a08.png basn4a08.pgm +png2pnm.exe -noraw ..\pngsuite\basn4a16.png basn4a16.pgm +REM -- color with alpha-channel +png2pnm.exe -noraw -alpha basn6a08.pgm ..\pngsuite\basn6a08.png basn6a08.ppm +png2pnm.exe -noraw -alpha basn6a16.pgm ..\pngsuite\basn6a16.png basn6a16.ppm +REM -- grayscale +png2pnm.exe -raw ..\pngsuite\basn0g01.png rawn0g01.pgm +png2pnm.exe -raw ..\pngsuite\basn0g02.png rawn0g02.pgm +png2pnm.exe -raw ..\pngsuite\basn0g04.png rawn0g04.pgm +png2pnm.exe -raw ..\pngsuite\basn0g08.png rawn0g08.pgm +png2pnm.exe -raw ..\pngsuite\basn0g16.png rawn0g16.pgm +REM -- full-color +png2pnm.exe -raw ..\pngsuite\basn2c08.png rawn2c08.ppm +png2pnm.exe -raw ..\pngsuite\basn2c16.png rawn2c16.ppm +REM -- palletted +png2pnm.exe -raw ..\pngsuite\basn3p01.png rawn3p01.ppm +png2pnm.exe -raw ..\pngsuite\basn3p02.png rawn3p02.ppm +png2pnm.exe -raw ..\pngsuite\basn3p04.png rawn3p04.ppm +png2pnm.exe -raw ..\pngsuite\basn3p08.png rawn3p08.ppm +REM -- gray with alpha-channel +png2pnm.exe -raw ..\pngsuite\basn4a08.png rawn4a08.pgm +png2pnm.exe -raw ..\pngsuite\basn4a16.png rawn4a16.pgm +REM -- color with alpha-channel +png2pnm.exe -noraw -alpha rawn6a08.pgm ..\pngsuite\basn6a08.png rawn6a08.ppm +png2pnm.exe -noraw -alpha rawn6a16.pgm ..\pngsuite\basn6a16.png rawn6a16.ppm + diff --git a/extern/libpng/include/contrib/pngminus/png2pnm.c b/extern/libpng/include/contrib/pngminus/png2pnm.c new file mode 100644 index 0000000000..a95acfa958 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/png2pnm.c @@ -0,0 +1,430 @@ +/* + * png2pnm.c --- conversion from PNG-file to PGM/PPM-file + * copyright (C) 1999 by Willem van Schaik + * + * version 1.0 - 1999.10.15 - First version. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. This software is provided "as is" without + * express or implied warranty. + */ + +#include +#include +#ifdef __TURBOC__ +#include +#include +#endif + +#ifndef BOOL +#define BOOL unsigned char +#endif +#ifndef TRUE +#define TRUE (BOOL) 1 +#endif +#ifndef FALSE +#define FALSE (BOOL) 0 +#endif + +#ifdef __TURBOC__ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 +#endif + +/* to make png2pnm verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +#define PNG_DEBUG 0 +#endif + +#include "png.h" + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* function prototypes */ + +int main (int argc, char *argv[]); +void usage (); +BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha); + +/* + * main + */ + +int main(int argc, char *argv[]) +{ + FILE *fp_rd = stdin; + FILE *fp_wr = stdout; + FILE *fp_al = NULL; + BOOL raw = TRUE; + BOOL alpha = FALSE; + int argi; + + for (argi = 1; argi < argc; argi++) + { + if (argv[argi][0] == '-') + { + switch (argv[argi][1]) + { + case 'n': + raw = FALSE; + break; + case 'r': + raw = TRUE; + break; + case 'a': + alpha = TRUE; + argi++; + if ((fp_al = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: can not create alpha-channel file %s\n", argv[argi]); + exit (1); + } + break; + case 'h': + case '?': + usage(); + exit(0); + break; + default: + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: unknown option %s\n", argv[argi]); + usage(); + exit(1); + break; + } /* end switch */ + } + else if (fp_rd == stdin) + { + if ((fp_rd = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: file %s does not exist\n", argv[argi]); + exit (1); + } + } + else if (fp_wr == stdout) + { + if ((fp_wr = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: can not create file %s\n", argv[argi]); + exit (1); + } + } + else + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: too many parameters\n"); + usage(); + exit(1); + } + } /* end for */ + +#ifdef __TURBOC__ + /* set stdin/stdout if required to binary */ + if (fp_rd == stdin) + { + setmode (STDIN, O_BINARY); + } + if ((raw) && (fp_wr == stdout)) + { + setmode (STDOUT, O_BINARY); + } +#endif + + /* call the conversion program itself */ + if (png2pnm (fp_rd, fp_wr, fp_al, raw, alpha) == FALSE) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: unsuccessful convertion of PNG-image\n"); + exit(1); + } + + /* close input file */ + fclose (fp_rd); + /* close output file */ + fclose (fp_wr); + /* close alpha file */ + if (alpha) + fclose (fp_al); + + return 0; +} + +/* + * usage + */ + +void usage() +{ + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, " by Willem van Schaik, 1999\n"); +#ifdef __TURBOC__ + fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); +#else + fprintf (stderr, " for Linux (and Unix) compilers\n"); +#endif + fprintf (stderr, "Usage: png2pnm [options] .png [.pnm]\n"); + fprintf (stderr, " or: ... | png2pnm [options]\n"); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -r[aw] write pnm-file in binary format (P4/P5/P6) (default)\n"); + fprintf (stderr, " -n[oraw] write pnm-file in ascii format (P1/P2/P3)\n"); + fprintf (stderr, " -a[lpha] .pgm write PNG alpha channel as pgm-file\n"); + fprintf (stderr, " -h | -? print this help-information\n"); +} + +/* + * png2pnm + */ + +BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha) +{ + png_struct *png_ptr = NULL; + png_info *info_ptr = NULL; + png_byte buf[8]; + png_byte *png_pixels = NULL; + png_byte **row_pointers = NULL; + png_byte *pix_ptr = NULL; + png_uint_32 row_bytes; + + png_uint_32 width; + png_uint_32 height; + int bit_depth; + int channels; + int color_type; + int alpha_present; + int row, col; + int ret; + int i; + long dep_16; + + /* read and check signature in PNG file */ + ret = fread (buf, 1, 8, png_file); + if (ret != 8) + return FALSE; + + ret = png_sig_cmp (buf, 0, 8); + if (ret) + return FALSE; + + /* create png and info structures */ + + png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (!png_ptr) + return FALSE; /* out of memory */ + + info_ptr = png_create_info_struct (png_ptr); + if (!info_ptr) + { + png_destroy_read_struct (&png_ptr, NULL, NULL); + return FALSE; /* out of memory */ + } + + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + return FALSE; + } + + /* set up the input control for C streams */ + png_init_io (png_ptr, png_file); + png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */ + + /* read the file information */ + png_read_info (png_ptr, info_ptr); + + /* get size and bit-depth of the PNG-image */ + png_get_IHDR (png_ptr, info_ptr, + &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + /* set-up the transformations */ + + /* transform paletted images into full-color rgb */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand (png_ptr); + /* expand images to bit-depth 8 (only applicable for grayscale images) */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand (png_ptr); + /* transform transparency maps into full alpha-channel */ + if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand (png_ptr); + +#ifdef NJET + /* downgrade 16-bit images to 8 bit */ + if (bit_depth == 16) + png_set_strip_16 (png_ptr); + /* transform grayscale images into full-color */ + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb (png_ptr); + /* only if file has a file gamma, we do a correction */ + if (png_get_gAMA (png_ptr, info_ptr, &file_gamma)) + png_set_gamma (png_ptr, (double) 2.2, file_gamma); +#endif + + /* all transformations have been registered; now update info_ptr data, + * get rowbytes and channels, and allocate image memory */ + + png_read_update_info (png_ptr, info_ptr); + + /* get the new color-type and bit-depth (after expansion/stripping) */ + png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + /* check for 16-bit files */ + if (bit_depth == 16) + { + raw = FALSE; +#ifdef __TURBOC__ + pnm_file->flags &= ~((unsigned) _F_BIN); +#endif + } + + /* calculate new number of channels and store alpha-presence */ + if (color_type == PNG_COLOR_TYPE_GRAY) + channels = 1; + else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + channels = 2; + else if (color_type == PNG_COLOR_TYPE_RGB) + channels = 3; + else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + channels = 4; + else + channels = 0; /* should never happen */ + alpha_present = (channels - 1) % 2; + + /* check if alpha is expected to be present in file */ + if (alpha && !alpha_present) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: PNG-file doesn't contain alpha channel\n"); + exit (1); + } + + /* row_bytes is the width x number of channels x (bit-depth / 8) */ + row_bytes = png_get_rowbytes (png_ptr, info_ptr); + + if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + return FALSE; + } + + if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) + { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + free (png_pixels); + png_pixels = NULL; + return FALSE; + } + + /* set the individual row_pointers to point at the correct offsets */ + for (i = 0; i < (height); i++) + row_pointers[i] = png_pixels + i * row_bytes; + + /* now we can go ahead and just read the whole image */ + png_read_image (png_ptr, row_pointers); + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end (png_ptr, info_ptr); + + /* clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); + + /* write header of PNM file */ + + if ((color_type == PNG_COLOR_TYPE_GRAY) || + (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + { + fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2"); + fprintf (pnm_file, "%d %d\n", (int) width, (int) height); + fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + else if ((color_type == PNG_COLOR_TYPE_RGB) || + (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) + { + fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3"); + fprintf (pnm_file, "%d %d\n", (int) width, (int) height); + fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + + /* write header of PGM file with alpha channel */ + + if ((alpha) && + ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || + (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2"); + fprintf (alpha_file, "%d %d\n", (int) width, (int) height); + fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + + /* write data to PNM file */ + pix_ptr = png_pixels; + + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + for (i = 0; i < (channels - alpha_present); i++) + { + if (raw) + fputc ((int) *pix_ptr++ , pnm_file); + else + if (bit_depth == 16){ + dep_16 = (long) *pix_ptr++; + fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++)); + } + else + fprintf (pnm_file, "%ld ", (long) *pix_ptr++); + } + if (alpha_present) + { + if (!alpha) + { + pix_ptr++; /* alpha */ + if (bit_depth == 16) + pix_ptr++; + } + else /* output alpha-channel as pgm file */ + { + if (raw) + fputc ((int) *pix_ptr++ , alpha_file); + else + if (bit_depth == 16){ + dep_16 = (long) *pix_ptr++; + fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++); + } + else + fprintf (alpha_file, "%ld ", (long) *pix_ptr++); + } + } /* if alpha_present */ + + if (!raw) + if (col % 4 == 3) + fprintf (pnm_file, "\n"); + } /* end for col */ + + if (!raw) + if (col % 4 != 0) + fprintf (pnm_file, "\n"); + } /* end for row */ + + if (row_pointers != (unsigned char**) NULL) + free (row_pointers); + if (png_pixels != (unsigned char*) NULL) + free (png_pixels); + + return TRUE; + +} /* end of source */ + diff --git a/extern/libpng/include/contrib/pngminus/png2pnm.sh b/extern/libpng/include/contrib/pngminus/png2pnm.sh new file mode 100644 index 0000000000..b1c05370df --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/png2pnm.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# -- grayscale +./png2pnm -noraw ../pngsuite/basn0g01.png basn0g01.pgm +./png2pnm -noraw ../pngsuite/basn0g02.png basn0g02.pgm +./png2pnm -noraw ../pngsuite/basn0g04.png basn0g04.pgm +./png2pnm -noraw ../pngsuite/basn0g08.png basn0g08.pgm +./png2pnm -noraw ../pngsuite/basn0g16.png basn0g16.pgm +# -- full-color +./png2pnm -noraw ../pngsuite/basn2c08.png basn2c08.ppm +./png2pnm -noraw ../pngsuite/basn2c16.png basn2c16.ppm +# -- palletted +./png2pnm -noraw ../pngsuite/basn3p01.png basn3p01.ppm +./png2pnm -noraw ../pngsuite/basn3p02.png basn3p02.ppm +./png2pnm -noraw ../pngsuite/basn3p04.png basn3p04.ppm +./png2pnm -noraw ../pngsuite/basn3p08.png basn3p08.ppm +# -- gray with alpha-channel +./png2pnm -noraw ../pngsuite/basn4a08.png basn4a08.pgm +./png2pnm -noraw ../pngsuite/basn4a16.png basn4a16.pgm +# -- color with alpha-channel +./png2pnm -noraw -alpha basn6a08.pgm ../pngsuite/basn6a08.png basn6a08.ppm +./png2pnm -noraw -alpha basn6a16.pgm ../pngsuite/basn6a16.png basn6a16.ppm +# -- grayscale +./png2pnm -raw ../pngsuite/basn0g01.png rawn0g01.pgm +./png2pnm -raw ../pngsuite/basn0g02.png rawn0g02.pgm +./png2pnm -raw ../pngsuite/basn0g04.png rawn0g04.pgm +./png2pnm -raw ../pngsuite/basn0g08.png rawn0g08.pgm +./png2pnm -raw ../pngsuite/basn0g16.png rawn0g16.pgm +# -- full-color +./png2pnm -raw ../pngsuite/basn2c08.png rawn2c08.ppm +./png2pnm -raw ../pngsuite/basn2c16.png rawn2c16.ppm +# -- palletted +./png2pnm -raw ../pngsuite/basn3p01.png rawn3p01.ppm +./png2pnm -raw ../pngsuite/basn3p02.png rawn3p02.ppm +./png2pnm -raw ../pngsuite/basn3p04.png rawn3p04.ppm +./png2pnm -raw ../pngsuite/basn3p08.png rawn3p08.ppm +# -- gray with alpha-channel +./png2pnm -raw ../pngsuite/basn4a08.png rawn4a08.pgm +./png2pnm -raw ../pngsuite/basn4a16.png rawn4a16.pgm +# -- color with alpha-channel +./png2pnm -noraw -alpha rawn6a08.pgm ../pngsuite/basn6a08.png rawn6a08.ppm +./png2pnm -noraw -alpha rawn6a16.pgm ../pngsuite/basn6a16.png rawn6a16.ppm + diff --git a/extern/libpng/include/contrib/pngminus/pngminus.bat b/extern/libpng/include/contrib/pngminus/pngminus.bat new file mode 100644 index 0000000000..911bb8dff9 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/pngminus.bat @@ -0,0 +1,4 @@ +make -f makefile.tc3 +call png2pnm.bat +call pnm2png.bat + diff --git a/extern/libpng/include/contrib/pngminus/pngminus.sh b/extern/libpng/include/contrib/pngminus/pngminus.sh new file mode 100644 index 0000000000..2a0a9d8fbb --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/pngminus.sh @@ -0,0 +1,5 @@ +#!/bin/sh +make -f makefile.std +sh png2pnm.sh +sh pnm2png.sh + diff --git a/extern/libpng/include/contrib/pngminus/pnm2png.bat b/extern/libpng/include/contrib/pngminus/pnm2png.bat new file mode 100644 index 0000000000..f756cb84de --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/pnm2png.bat @@ -0,0 +1,41 @@ +REM -- grayscale +pnm2png.exe basn0g01.pgm basn0g01.png +pnm2png.exe basn0g02.pgm basn0g02.png +pnm2png.exe basn0g04.pgm basn0g04.png +pnm2png.exe basn0g08.pgm basn0g08.png +pnm2png.exe basn0g16.pgm basn0g16.png +REM -- full-color +pnm2png.exe basn2c08.ppm basn2c08.png +pnm2png.exe basn2c16.ppm basn2c16.png +REM -- palletted +pnm2png.exe basn3p01.ppm basn3p01.png +pnm2png.exe basn3p02.ppm basn3p02.png +pnm2png.exe basn3p04.ppm basn3p04.png +pnm2png.exe basn3p08.ppm basn3p08.png +REM -- gray with alpha-channel +pnm2png.exe -alpha basn6a08.pgm basn4a08.pgm basn4a08.png +pnm2png.exe -alpha basn6a16.pgm basn4a16.pgm basn4a16.png +REM -- color with alpha-channel +pnm2png.exe -alpha basn6a08.pgm basn6a08.ppm basn6a08.png +pnm2png.exe -alpha basn6a16.pgm basn6a16.ppm basn6a16.png +REM -- grayscale +pnm2png.exe rawn0g01.pgm rawn0g01.png +pnm2png.exe rawn0g02.pgm rawn0g02.png +pnm2png.exe rawn0g04.pgm rawn0g04.png +pnm2png.exe rawn0g08.pgm rawn0g08.png +pnm2png.exe rawn0g16.pgm rawn0g16.png +REM -- full-color +pnm2png.exe rawn2c08.ppm rawn2c08.png +pnm2png.exe rawn2c16.ppm rawn2c16.png +REM -- palletted +pnm2png.exe rawn3p01.ppm rawn3p01.png +pnm2png.exe rawn3p02.ppm rawn3p02.png +pnm2png.exe rawn3p04.ppm rawn3p04.png +pnm2png.exe rawn3p08.ppm rawn3p08.png +REM -- gray with alpha-channel +pnm2png.exe -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png +pnm2png.exe -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png +REM -- color with alpha-channel +pnm2png.exe -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png +pnm2png.exe -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png + diff --git a/extern/libpng/include/contrib/pngminus/pnm2png.c b/extern/libpng/include/contrib/pngminus/pnm2png.c new file mode 100644 index 0000000000..4cdfad8313 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/pnm2png.c @@ -0,0 +1,533 @@ +/* + * pnm2png.c --- conversion from PBM/PGM/PPM-file to PNG-file + * copyright (C) 1999 by Willem van Schaik + * + * version 1.0 - 1999.10.15 - First version. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. This software is provided "as is" without + * express or implied warranty. + */ + +#include +#include +#ifdef __TURBOC__ +#include +#include +#endif + +#ifndef BOOL +#define BOOL unsigned char +#endif +#ifndef TRUE +#define TRUE (BOOL) 1 +#endif +#ifndef FALSE +#define FALSE (BOOL) 0 +#endif + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +/* to make pnm2png verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +#define PNG_DEBUG 0 +#endif + +#include "png.h" + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* function prototypes */ + +int main (int argc, char *argv[]); +void usage (); +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha); +void get_token(FILE *pnm_file, char *token); +png_uint_32 get_data (FILE *pnm_file, int depth); +png_uint_32 get_value (FILE *pnm_file, int depth); + +/* + * main + */ + +int main(int argc, char *argv[]) +{ + FILE *fp_rd = stdin; + FILE *fp_al = NULL; + FILE *fp_wr = stdout; + BOOL interlace = FALSE; + BOOL alpha = FALSE; + int argi; + + for (argi = 1; argi < argc; argi++) + { + if (argv[argi][0] == '-') + { + switch (argv[argi][1]) + { + case 'i': + interlace = TRUE; + break; + case 'a': + alpha = TRUE; + argi++; + if ((fp_al = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: alpha-channel file %s does not exist\n", + argv[argi]); + exit (1); + } + break; + case 'h': + case '?': + usage(); + exit(0); + break; + default: + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: unknown option %s\n", argv[argi]); + usage(); + exit(1); + break; + } /* end switch */ + } + else if (fp_rd == stdin) + { + if ((fp_rd = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: file %s does not exist\n", argv[argi]); + exit (1); + } + } + else if (fp_wr == stdout) + { + if ((fp_wr = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: can not create PNG-file %s\n", argv[argi]); + exit (1); + } + } + else + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: too many parameters\n"); + usage(); + exit (1); + } + } /* end for */ + +#ifdef __TURBOC__ + /* set stdin/stdout to binary, we're reading the PNM always! in binary format */ + if (fp_rd == stdin) + { + setmode (STDIN, O_BINARY); + } + if (fp_wr == stdout) + { + setmode (STDOUT, O_BINARY); + } +#endif + + /* call the conversion program itself */ + if (pnm2png (fp_rd, fp_wr, fp_al, interlace, alpha) == FALSE) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: unsuccessful converting to PNG-image\n"); + exit (1); + } + + /* close input file */ + fclose (fp_rd); + /* close output file */ + fclose (fp_wr); + /* close alpha file */ + if (alpha) + fclose (fp_al); + + return 0; +} + +/* + * usage + */ + +void usage() +{ + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, " by Willem van Schaik, 1999\n"); +#ifdef __TURBOC__ + fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); +#else + fprintf (stderr, " for Linux (and Unix) compilers\n"); +#endif + fprintf (stderr, "Usage: pnm2png [options] . [.png]\n"); + fprintf (stderr, " or: ... | pnm2png [options]\n"); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -i[nterlace] write png-file with interlacing on\n"); + fprintf (stderr, " -a[lpha] .pgm read PNG alpha channel as pgm-file\n"); + fprintf (stderr, " -h | -? print this help-information\n"); +} + +/* + * pnm2png + */ + +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha) +{ + png_struct *png_ptr = NULL; + png_info *info_ptr = NULL; + png_byte *png_pixels = NULL; + png_byte **row_pointers = NULL; + png_byte *pix_ptr = NULL; + png_uint_32 row_bytes; + + char type_token[16]; + char width_token[16]; + char height_token[16]; + char maxval_token[16]; + int color_type; + png_uint_32 width, alpha_width; + png_uint_32 height, alpha_height; + png_uint_32 maxval; + int bit_depth = 0; + int channels; + int alpha_depth = 0; + int alpha_present; + int row, col; + BOOL raw, alpha_raw = FALSE; + png_uint_32 tmp16; + int i; + + /* read header of PNM file */ + + get_token(pnm_file, type_token); + if (type_token[0] != 'P') + { + return FALSE; + } + else if ((type_token[1] == '1') || (type_token[1] == '4')) + { + raw = (type_token[1] == '4'); + color_type = PNG_COLOR_TYPE_GRAY; + bit_depth = 1; + } + else if ((type_token[1] == '2') || (type_token[1] == '5')) + { + raw = (type_token[1] == '5'); + color_type = PNG_COLOR_TYPE_GRAY; + get_token(pnm_file, width_token); + sscanf (width_token, "%lu", &width); + get_token(pnm_file, height_token); + sscanf (height_token, "%lu", &height); + get_token(pnm_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + bit_depth = 1; + else if (maxval <= 3) + bit_depth = 2; + else if (maxval <= 15) + bit_depth = 4; + else if (maxval <= 255) + bit_depth = 8; + else /* if (maxval <= 65535) */ + bit_depth = 16; + } + else if ((type_token[1] == '3') || (type_token[1] == '6')) + { + raw = (type_token[1] == '6'); + color_type = PNG_COLOR_TYPE_RGB; + get_token(pnm_file, width_token); + sscanf (width_token, "%lu", &width); + get_token(pnm_file, height_token); + sscanf (height_token, "%lu", &height); + get_token(pnm_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + bit_depth = 1; + else if (maxval <= 3) + bit_depth = 2; + else if (maxval <= 15) + bit_depth = 4; + else if (maxval <= 255) + bit_depth = 8; + else /* if (maxval <= 65535) */ + bit_depth = 16; + } + else + { + return FALSE; + } + + /* read header of PGM file with alpha channel */ + + if (alpha) + { + if (color_type == PNG_COLOR_TYPE_GRAY) + color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + if (color_type == PNG_COLOR_TYPE_RGB) + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + get_token(alpha_file, type_token); + if (type_token[0] != 'P') + { + return FALSE; + } + else if ((type_token[1] == '2') || (type_token[1] == '5')) + { + alpha_raw = (type_token[1] == '5'); + get_token(alpha_file, width_token); + sscanf (width_token, "%lu", &alpha_width); + if (alpha_width != width) + return FALSE; + get_token(alpha_file, height_token); + sscanf (height_token, "%lu", &alpha_height); + if (alpha_height != height) + return FALSE; + get_token(alpha_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + alpha_depth = 1; + else if (maxval <= 3) + alpha_depth = 2; + else if (maxval <= 15) + alpha_depth = 4; + else if (maxval <= 255) + alpha_depth = 8; + else /* if (maxval <= 65535) */ + alpha_depth = 16; + if (alpha_depth != bit_depth) + return FALSE; + } + else + { + return FALSE; + } + } /* end if alpha */ + + /* calculate the number of channels and store alpha-presence */ + if (color_type == PNG_COLOR_TYPE_GRAY) + channels = 1; + else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + channels = 2; + else if (color_type == PNG_COLOR_TYPE_RGB) + channels = 3; + else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + channels = 4; + else + channels = 0; /* should not happen */ + + alpha_present = (channels - 1) % 2; + + /* row_bytes is the width x number of channels x (bit-depth / 8) */ + row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); + + if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) + return FALSE; + + /* read data from PNM file */ + pix_ptr = png_pixels; + + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + for (i = 0; i < (channels - alpha_present); i++) + { + if (raw) + *pix_ptr++ = get_data (pnm_file, bit_depth); + else + if (bit_depth <= 8) + *pix_ptr++ = get_value (pnm_file, bit_depth); + else + { + tmp16 = get_value (pnm_file, bit_depth); + *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF); + pix_ptr++; + *pix_ptr = (png_byte) (tmp16 & 0xFF); + pix_ptr++; + } + } + + if (alpha) /* read alpha-channel from pgm file */ + { + if (alpha_raw) + *pix_ptr++ = get_data (alpha_file, alpha_depth); + else + if (alpha_depth <= 8) + *pix_ptr++ = get_value (alpha_file, bit_depth); + else + { + tmp16 = get_value (alpha_file, bit_depth); + *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); + *pix_ptr++ = (png_byte) (tmp16 & 0xFF); + } + } /* if alpha */ + + } /* end for col */ + } /* end for row */ + + /* prepare the standard PNG structures */ + png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + return FALSE; + } + info_ptr = png_create_info_struct (png_ptr); + if (!info_ptr) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + + /* setjmp() must be called in every function that calls a PNG-reading libpng function */ + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + + /* initialize the png structure */ + png_init_io (png_ptr, png_file); + + /* we're going to write more or less the same PNG as the input file */ + png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, + (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* write the file header information */ + png_write_info (png_ptr, info_ptr); + + /* if needed we will allocate memory for an new array of row-pointers */ + if (row_pointers == (unsigned char**) NULL) + { + if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + } + + /* set the individual row_pointers to point at the correct offsets */ + for (i = 0; i < (height); i++) + row_pointers[i] = png_pixels + i * row_bytes; + + /* write out the entire image data in one call */ + png_write_image (png_ptr, row_pointers); + + /* write the additional chuncks to the PNG file (not really needed) */ + png_write_end (png_ptr, info_ptr); + + /* clean up after the write, and free any memory allocated */ + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + + if (row_pointers != (unsigned char**) NULL) + free (row_pointers); + if (png_pixels != (unsigned char*) NULL) + free (png_pixels); + + return TRUE; +} /* end of pnm2png */ + +/* + * get_token() - gets the first string after whitespace + */ + +void get_token(FILE *pnm_file, char *token) +{ + int i = 0; + + /* remove white-space */ + do + { + token[i] = (unsigned char) fgetc (pnm_file); + } + while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); + + /* read string */ + do + { + i++; + token[i] = (unsigned char) fgetc (pnm_file); + } + while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); + + token[i] = '\0'; + + return; +} + +/* + * get_data() - takes first byte and converts into next pixel value, + * taking as much bits as defined by bit-depth and + * using the bit-depth to fill up a byte (0Ah -> AAh) + */ + +png_uint_32 get_data (FILE *pnm_file, int depth) +{ + static int bits_left = 0; + static int old_value = 0; + static int mask = 0; + int i; + png_uint_32 ret_value; + + if (mask == 0) + for (i = 0; i < depth; i++) + mask = (mask >> 1) | 0x80; + + if (bits_left <= 0) + { + old_value = fgetc (pnm_file); + bits_left = 8; + } + + ret_value = old_value & mask; + for (i = 1; i < (8 / depth); i++) + ret_value = ret_value || (ret_value >> depth); + + old_value = (old_value << depth) & 0xFF; + bits_left -= depth; + + return ret_value; +} + +/* + * get_value() - takes first (numeric) string and converts into number, + * using the bit-depth to fill up a byte (0Ah -> AAh) + */ + +png_uint_32 get_value (FILE *pnm_file, int depth) +{ + static png_uint_32 mask = 0; + png_byte token[16]; + png_uint_32 ret_value; + int i = 0; + + if (mask == 0) + for (i = 0; i < depth; i++) + mask = (mask << 1) | 0x01; + + get_token (pnm_file, (char *) token); + sscanf ((const char *) token, "%lu", &ret_value); + + ret_value &= mask; + + if (depth < 8) + for (i = 0; i < (8 / depth); i++) + ret_value = (ret_value << depth) || ret_value; + + return ret_value; +} + +/* end of source */ + diff --git a/extern/libpng/include/contrib/pngminus/pnm2png.sh b/extern/libpng/include/contrib/pngminus/pnm2png.sh new file mode 100644 index 0000000000..d79df2fae0 --- /dev/null +++ b/extern/libpng/include/contrib/pngminus/pnm2png.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# -- grayscale +./pnm2png basn0g01.pgm basn0g01.png +./pnm2png basn0g02.pgm basn0g02.png +./pnm2png basn0g04.pgm basn0g04.png +./pnm2png basn0g08.pgm basn0g08.png +./pnm2png basn0g16.pgm basn0g16.png +# -- full-color +./pnm2png basn2c08.ppm basn2c08.png +./pnm2png basn2c16.ppm basn2c16.png +# -- palletted +./pnm2png basn3p01.ppm basn3p01.png +./pnm2png basn3p02.ppm basn3p02.png +./pnm2png basn3p04.ppm basn3p04.png +./pnm2png basn3p08.ppm basn3p08.png +# -- gray with alpha-channel +./pnm2png -alpha basn6a08.pgm basn4a08.pgm basn4a08.png +./pnm2png -alpha basn6a16.pgm basn4a16.pgm basn4a16.png +# -- color with alpha-channel +./pnm2png -alpha basn6a08.pgm basn6a08.ppm basn6a08.png +./pnm2png -alpha basn6a16.pgm basn6a16.ppm basn6a16.png +# -- grayscale +./pnm2png rawn0g01.pgm rawn0g01.png +./pnm2png rawn0g02.pgm rawn0g02.png +./pnm2png rawn0g04.pgm rawn0g04.png +./pnm2png rawn0g08.pgm rawn0g08.png +./pnm2png rawn0g16.pgm rawn0g16.png +# -- full-color +./pnm2png rawn2c08.ppm rawn2c08.png +./pnm2png rawn2c16.ppm rawn2c16.png +# -- palletted +./pnm2png rawn3p01.ppm rawn3p01.png +./pnm2png rawn3p02.ppm rawn3p02.png +./pnm2png rawn3p04.ppm rawn3p04.png +./pnm2png rawn3p08.ppm rawn3p08.png +# -- gray with alpha-channel +./pnm2png -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png +./pnm2png -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png +# -- color with alpha-channel +./pnm2png -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png +./pnm2png -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png + diff --git a/extern/libpng/include/contrib/pngsuite/README b/extern/libpng/include/contrib/pngsuite/README new file mode 100644 index 0000000000..714baff2b2 --- /dev/null +++ b/extern/libpng/include/contrib/pngsuite/README @@ -0,0 +1,102 @@ + +pngsuite +-------- +(c) Willem van Schaik, 1999, 2011 + +Permission to use, copy, modify, and distribute these images for any +purpose and without fee is hereby granted. + +The 15 "bas*.png" images are part of the much larger PngSuite test-set of +images, available for developers of PNG supporting software. The +complete set, available at http:/www.schaik.com/pngsuite/, contains +a variety of images to test interlacing, gamma settings, ancillary +chunks, etc. + +The "ft*.png" images are "free/libre" replacements for the transparent +corresponding t*.png images in the PngSuite. + +The images in this directory represent the basic PNG color-types: +grayscale (1-16 bit deep), full color (8 or 16 bit), paletted +(1-8 bit) and grayscale or color images with alpha channel. You +can use them to test the proper functioning of PNG software. + + filename depth type + ------------ ------ -------------- + basn0g01.png 1-bit grayscale + basn0g02.png 2-bit grayscale + basn0g04.png 4-bit grayscale + basn0g08.png 8-bit grayscale + basn0g16.png 16-bit grayscale + basn2c08.png 8-bit truecolor + basn2c16.png 16-bit truecolor + basn3p01.png 1-bit paletted + basn3p02.png 2-bit paletted + basn3p04.png 4-bit paletted + basn3p08.png 8-bit paletted + basn4a08.png 8-bit gray with alpha + basn4a16.png 16-bit gray with alpha + basn6a08.png 8-bit RGBA + basn6a16.png 16-bit RGBA + + ftbbn0g04.png 4-bit grayscale, black bKGD + ftbbn2c16.png 16-bit truecolor, black bKGD + ftbbn3p08.png 8-bit paletted, black bKGD + ftbgn2c16.png 16-bit truecolor, gray bKGD + ftbgn3p08.png 8-bit paletted, gray bKGD + ftbrn2c08.png 8-bit truecolor, red bKGD + ftbwn0g16.png 16-bit gray, white bKGD + ftbwn3p08.png 8-bit paletted, white bKGD + ftbyn3p08.png 8-bit paletted, yellow bKGD + ftp0n0g08.png 8-bit grayscale, opaque + ftp0n2c08.png 8-bit truecolor, opaque + ftp0n3p08.png 8-bit paletted, opaque + ftp1n3p08.png 8-bit paletted, no bKGD + +Here is the correct result of typing "pngtest -m bas*.png" in +this directory: + +Testing basn0g01.png: PASS (524 zero samples) + Filter 0 was used 32 times +Testing basn0g02.png: PASS (448 zero samples) + Filter 0 was used 32 times +Testing basn0g04.png: PASS (520 zero samples) + Filter 0 was used 32 times +Testing basn0g08.png: PASS (3 zero samples) + Filter 1 was used 9 times + Filter 4 was used 23 times +Testing basn0g16.png: PASS (1 zero samples) + Filter 1 was used 1 times + Filter 2 was used 31 times +Testing basn2c08.png: PASS (6 zero samples) + Filter 1 was used 5 times + Filter 4 was used 27 times +Testing basn2c16.png: PASS (592 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn3p01.png: PASS (512 zero samples) + Filter 0 was used 32 times +Testing basn3p02.png: PASS (448 zero samples) + Filter 0 was used 32 times +Testing basn3p04.png: PASS (544 zero samples) + Filter 0 was used 32 times +Testing basn3p08.png: PASS (4 zero samples) + Filter 0 was used 32 times +Testing basn4a08.png: PASS (32 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn4a16.png: PASS (64 zero samples) + Filter 0 was used 1 times + Filter 1 was used 2 times + Filter 2 was used 1 times + Filter 4 was used 28 times +Testing basn6a08.png: PASS (160 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn6a16.png: PASS (1072 zero samples) + Filter 1 was used 4 times + Filter 4 was used 28 times +libpng passes test + +Willem van Schaik + +October 1999 diff --git a/extern/libpng/include/contrib/pngsuite/basn0g01.png b/extern/libpng/include/contrib/pngsuite/basn0g01.png new file mode 100644 index 0000000000000000000000000000000000000000..e31e1c7a635b50e22b6d02ab8ba21f8099b39faa GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^3Lwk~Bp9L@-6Me%OS+@4BLidG0>c;6;z7cmE{-7_ zGj-2wzopr084i?r2qf` literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn0g02.png b/extern/libpng/include/contrib/pngsuite/basn0g02.png new file mode 100644 index 0000000000000000000000000000000000000000..68809dd8fc0993ddebce8aa9c7bf9bbecbd36cfc GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3Lwk`Bp75C+I9jdmUKs7M+U~W1%@xC#RK{Bo-U3d y5>t~CIAXub_k1+y2sp$L+}6)%%qgEdVJADoUeEf*_U-^?kP)7)elF{r5}E*i=NeZ4 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn0g04.png b/extern/libpng/include/contrib/pngsuite/basn0g04.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa089cb8a4ba0e8421ea05d33676856f0cac93c GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^3Lwk^Bp4c;6;(>fePZ!4! zi{9jv1QiAmjuV@CSXq1cIW&KKm$y%-G>{Q7I3+kCJ!Mg43=bP?PydHg|Nfu<(f+K^ hPy#6PU}|a#3q!!ue}#oBxm7@xc)I$ztaD0e0szfSD4qZS literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn0g16.png b/extern/libpng/include/contrib/pngsuite/basn0g16.png new file mode 100644 index 0000000000000000000000000000000000000000..318ebcadf4fd0b64fb9b824e81c0cc8e3dfd2d82 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^3Lq>1BpBEle`W(ImUKs7M+U~W1%@xC#RK_qo-U3d z9-UV&8FC#k;BgMLjDBB#?9PJ82Q;dUu4=I?zS(bY(Xf0+xUg{Y0;{G3S&o?ucbmRB zoML$)c8ASL&0+fj+X+UDyI8k3PT;(to58=tC&50S{f++@NsIIK3}QFDZ^ZA8J8=o* N0#8>zmvv4FO#l#XIHLdn literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn2c08.png b/extern/libpng/include/contrib/pngsuite/basn2c08.png new file mode 100644 index 0000000000000000000000000000000000000000..21d2f91a868fc637fdae4fba6c87bfd09b158815 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={WSkfJR9T^zg78t&m77yfmc)B=- zcyzwKdXSUBfQQMU_07b;+lz#)U9`U}{BiD~_7+|i>jo~7A2JKxKB@JoaA;)W_iC3v r)WR;J@nJ!Uh4M;=#@z+wiw`h1ZTuN$cYX2NTxus~-YE?|ew94KIo9tHTv?hhRR zwrA%J^h9UxCeRmyPjW#d?oxNFL9(uFDZ1gBle+D$rIj`J+5;}Xa zfF63WfGT3xy1iYa$zve>zUQQss#Q*>R07*qoM6N<$g1`fR ASpWb4 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn3p01.png b/extern/libpng/include/contrib/pngsuite/basn3p01.png new file mode 100644 index 0000000000000000000000000000000000000000..a21db5977462c4c0985a0ca1ac2d67ec572d3d17 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;SkfJR9T^zg78t&m77ygJ1^9%x zzWcAFl=eSI>XI5zMAXy8F@$4g@&k4zHj_up0tD0@h%3W?AY}Lt#0>va?X`CSX(dk=#}J9B$v@Vz>816FsF9(VN75txh7sS~8e>Vez z3y|e5zLEEca@?OO&kPSTILuD+yidi?7W^QF z0=7twg95}IGPB`0p){BIDdQnXEGb?R1lBYr!w>|Li8PIP)G{}a$YQ`p%(`K)LO3UD z6M@=IHq>+iwp~U6B7p@ho9?k)W)s^cNfJ5alp|5o3vi!RBHkmgX}UWIuw)VII#g=d z$04w7jssURBxceP_z6C6HW{SZU_uGkHHZpyqy!k&kY2+c1*akQFoehhD3_nQ9ng;b z0F#8v3ad!gP>4LFqCR|KhXmq>PACHhpyFVSOH8CTvPiZqN$iqqnyfQJ&?bvale$n1 zTv^)Th9oKqsKIPjfKCD1Cd3{VRFz%0i$*94z+D%LEeH_80824wDGaq4ThALK_0kH^LL!W!ET%TWXjP zf+UjIVU&gj2dkjg55o;~Er9W|;Xj52QG;=_Fb4{JL{~@@LhLOJ3noJ*c>^l+tMCGO zCYz+He>Pl<|Ld_f zqkm1#%jMM-%}evv+<)~($raC^D<>wy%g2N5PX<@DWeyA$O75|=jlHcE2YqXoq<-r^ zSF~%HYo3ID?48vDt>55dBr2eB{o9GWV*`fG5Jx3PvhgDLYTpZ#Qi+|CPMFK>V8kJOfm z#*Z=w{NC;LVI4^y_wGIZ+0l95T|3etXWUAydp~nc!u}QYkLn)pJU@Hlx;E!j?tzqu zY2yX+->z>?3??Uzz4BVazO+Xz%j8eHAEZy_UHonH-GsLIpF6E1$sG&stX%!v*c@Yf zL&of5NeNZAyW0FGPYv%K9`*NV3kUPJUh!4N^d%dUzFDUR&e(zJm#a=^UXXnc(yA(I z-;o2p70nAqE-$V851jZH`@`rk4UEa{HEjtq=#3k+XOiwE*eJzX3_ zJUWyAoIh}Yv2{*{iJ{UQo%@m+%sTdM`xqA|8c4B)7$%qqxF2rNV(Vdhlpzstn1SKG XmO|}<{e=-g0~kDA{an^LB{Ts5zRx3; literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn4a16.png b/extern/libpng/include/contrib/pngsuite/basn4a16.png new file mode 100644 index 0000000000000000000000000000000000000000..6dbee9fbdb93f3535be23326a52fb4d3ac60711e GIT binary patch literal 2206 zcmV;P2x0e$P)kEEkx>-b1@Qb$y-ohUek5*oTfx-A#6y^c`Q zE+sS)yU66wLTO83iFXm5i(N>*n3Idp^rFd-7Fe(v0)u8Hg(Rko(t3o_;+1WoY3fR? z;u%**k?mvsIhJ?vei@;3*EJZKPsh^xKJW8B&+`FbWnox{J*QyQf)~!hu>m;#N5~Gr z*+0X@UGUyz_~;4v=U?IOURb{_zjyb_*+);vGZ%Ns|73^cGmZ_&XO3F(9mBeOCxB*U zp=MjTt{LzZp}PWF5dym*a0v7!gx-ecb!ZpC(_mu+I?n=c$cJ>2a^`8!UXW*-DOjHb z_YkaIf>i_R6{x46R)AUxtZXgQHLOFeVC9@tBpY?%Ar~H6|39xka0c+50pEqb_xeL; z>a}V>WX7?rbSB#R07d+ApMY-yAH>T3O$tpzVWT4D`KV9D#5e8fT$B0UQ0W`4d&ZJhZPsBMV$%MrM45S^qKLL>pn6E&%2tD%( zfxsaMlx61rFQs$e8K{_6R*OS$5R5?x4}vuajX`MdfzF^5&@Mrv1ZyRz{~eqXESKOv zC8(4kRQ&NCC3e`!t zTZ4s<;Z`0-CLBBdHEi7qkvf2J|EZXCOGP5NH>n6_-74c*6GZ37L6suXG-K z4CW`TtWk#kGCXQS`*SIvW& ze;)x)gZ678GOZ6~)z<4mILi{)`)Xj6VJ;rYMiMZbfJQTN3< z-w!`MDg}Ig4z9ir2NE@VR~cfbAbJpyzjJG1I)@lji+);sjI05nfaPE90J3cN2oI4LMzvS4Dmtmj`)-)Kipf5lm0R9Eg z($KwIiQO+n{(bK$1b72BlcMdLkBGu;UX?xXbcF5RDVcdAA)Swp!;446R4=_#v$t=D zz6+p#1O8K>O@QxD;PZj64qX$_)dyW8(DgUyDgtM~$B+D@)ok(ejv=nLaagq78xe(T zwPerTQDOVyHJSOj^U^uMi$~z)m*DX-4D18zgc`veH3Ac~yc)q}HG(AgY|tG00TSjE z39l#;mV|^Wv$E%vxUl`|`!e(G+og+_Uy_0jBw$w@Vv`WfKS07T1Ph9UIYq+fpnH!( z;D2j4rPeSn#&p)`Qj5U(Rr4MKU)UxPqX ztzk;7p<_#oYK2so@RX&V5M!xUMP3&^7LnOocI;h>?fN%Tz`#D~+=;_n9NcNR_n;7s zK<_CC-2h!vLX-smkV2q&9h#r2B=eN=^OCsQ(voQVt-L7Q&L?Hht!ZI9$joDt(z!bg z^OMk=0QYNHU4=*(%mVbj1IA4y#YrW_j;#XZ?^TR?UBZO(f>>&$BE~W@;n+h@D`@Wu z$+QV6z?hYpZ?mNH=7bd79)?B(Toc^9GNU(@8Kod-D+Jaj!40VlcSDlQ@=@{gQdwLr z{7&Zb}S~Y7L5w23`5q-r&J^mkTcViXI59GbI+3oJQLb^Xa=CM0~+5#BMC-O zA+UA{R^F8K>THn=w^)!Q^Kf1Hd0kwsr!Ly=Ul4@@*>gQCY&S<_=B_E7dnQy&=%m3* zDCd0zS}ADFD+E>zs2dWUs|O`O4x}A>>t~W=B5CF4X>qmStD@~)iUV3+_B@mqwwnc+ zd9xs$chb^OXB50E(5^x|39aW80`&^qb0xPgtMuBRkPK&4ggm`H%Fo9{P`Y=EwuAib zKPY=1x*=>g=Va#1fOOs&mBuk$A(S{Hf;FuuV#)d7sbeoV@Fcz z#`3Pp?K3L97A3<4ijriy)kU_eC)4|}U(UH||907*qoM6N<$f-(OD1poj5 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/basn6a08.png b/extern/libpng/include/contrib/pngsuite/basn6a08.png new file mode 100644 index 0000000000000000000000000000000000000000..61062308548bc3a5255e3e8dbb7f97932f00eb1c GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+U~W1%@xC#RK{Io-U3d z5v^~p8FDok@VGrxPs#9K_}xB~rC;&L-J`A*vOzBbH2%o@YTWE%G>EINoAZB{akFeG zt2^^4wiQ2lBNnjxnaU~EHpDcAJeJR?S{LDp`Fk}h0vV{=c>|`0F zY}t2XhO#pw*@@4+-}ija_s93gIp?4AJnwVP`=0Zh6Lm*li-YYn8vpunKbAURdar&!F_@9SoS%FU_nL5v4bhxdo;qYV}(%9Z85QFC@Q_IDD58Vx)&SPd#1 z&_z21b`BlfZb@Z16}%Yv2Xg?CHRMe7qkJ)iJY&NQ*3GZeU+ur74iHv1P36E6yN%N5 zpV$8~7z8Rae`?A#-PAcaas4$5zYproUQo8+k=bWG?@3hw>tAT`15|X+#pzBR*EFaZTfujS2W+R%rAX5GszY`8KG_1tm1wxz^bYuH^_iu1 z#`8Dkd|UXn0~66IH5Y)%1^wg@FJA3z9$T7YRh1FE(o z&iHoiEcavc!3({fssSC{c=<uH$6|lJ`Cw^#7+?9Oeh5*sk;TrZA_sxq|m5T=dEMGV0i z^PYDhxn{(1ZN~3SMiq)&y^i@u;6U{BWs8VI#ZOVtSIoPu#Uy>G@F^}60slpM% z4fg4f0@c(&o=lnNB5(wh%7VCL!-EVW2Z|!o{aAn*D%&65S@(Uw9aQtxwD)dfkbS0D zN4fECZ9%?vJvB6eQZ4WGA92VxeEjiXK}uR*cR55gZ_cQBgwFlZzlpoCI^@-;A(;$?Ag&)@JLm6Q6RE$C5WB$XVqD_cH4>}=w0RmK|UFq zqT&JFo{xshQhkO07xrmHL>wC3kOr5B~p#zX7$p_c_}QIK>i^mAbP z(RxI|(i~*Q0#6E}svtMT(M} zh+aH!wG#=NVm~3Dv%@S5-kh)W{c#dFYEqq2IfIFM+s<@5JzKFU(kzGaEKDY05{~)y z&m>r1+fS3X-!8#9ZC}|9nR|zJTO|nFEi^1Tfpt@Ll^mIY?oP}|^w=aDOTn=uec<16y1Ij2viXQ-skm0LAjJTsD=F!#DdRhpGW%{rtjIuduzuQ<{wdf>RTZ$_*JNG)(wu0^Ec6FbT<6xqSx? z_!3zIUUfCS)6fLwA!%9Yvs}RFb1bBZaM#FX`Dt@6LHtQA1;AaBd4qVKP{nI32V#wJ z&XhLUx0p{l^jo|vK~SZ`ptJ4mne>h=EQ)IBapSiJu{K;#J#&J6T*;znj93+*IlB6?-&YMGi|#xn!fR)W?0*~Y-v zJb%t6l>}jz9_AsI@@RuRW(OUfTdY%wuhTG}3Ve9pnfH+Qw4C3B8)Pv=6}W4d99_e^ z#9AT03q=Y1K=%(%UJPCeUhitoH`-hON*?knX(%Hos$uAK073oP!1*Xq-mClxyor$@ z}heD;=s0m{le|mRTbo3Wp+E$278tBRf$HlP|fM)?++96CPyL1+wsjf zVk53I^h-S=*7nAhx<|s)bJ8w@jBPCFcgym*E9ryTcW-vs2fn~wpR?z?3`C&?_rYej3k<^}V2IPiv-8;{mgi2hH ztlSGT$s1@-?Cm1cFWbX9F{sRWv(?cibljVBrb znh0Bb)h@WE8=d#nxg!?mgZ_jv{v*Mtb>{rWq@mQ%GO4pYbYY3NhtwS%vk@F6@Cv0q z;32kUm2%K;GCpIm7nY^O2baB-b57D+>*@DbC6}<(k6UKuV_t7>0Ad1l2vQK9%E7Iu z&(5t^!vq|;yR##&(?y9Bxh>PK;x24md0z_`OZ&EXN0znDnHMLgT0vE z_yTz|TbH$rwir9{GXE3${#InnMxfp1xrN`krccn6rI*N0fJ7fVs@lf)c+k@Bj%@7x zn2jh^(!=IcnGPq-s=mA+pAQRc3WQ}3(CFdc(eD`%-gjE}`d9j0woiiIO||T#+v6=j zd(Vm%BvEfmcrs6v+tJ!B*r>Oomj6Yn^vw~qcjX^|m%*OM51be;(%YN8T!+aSl}jzO z!y8LjI?!s%Jnta+*LWjuuoDMp8d{FnQWAsFx^5}~^aqjGKt--Tz&i+DWSigz|HVB- z?p9v``EK^JY(aBjc6TFYcV~A?IDo|@Q%5w24{w**chBHLlrK0ny!nC(PsT1>Hqnih z{Bkl=fi=xu0ZFjuFh^xM2sQ&sXR~!_Qd=m2&L2Axw6>g3OQD`iWxG zSjeAUfi`M4@n+JdMglmRaM{EnaIoCk%7r&sK1kSNCR{49-Ta zj?6y#Lz!(+99uqME>10f)qmtbigTu-hI=Xb4zcPc{eH2y_7vv*s( z*^3PwpUJg-5C=DiVuy>>a!|8$e5K?M)}J02FLf0O{QRMti|gU9yM zpsH)mY4IMnhuIeGf1AoYPn=%bN?oV&q3&xZP#{- zd#wGeV8okcyH@o)cboHb1rrf^jB^?sG2T2?@G1n)CJc@hyhCf)&E8%^0~1oF;v>7S z;6sBJiji@r0Yq=mmR;)Ojr>$W46R-Sau7HO7xZFtI1{|4z%-nLbW=B z3o0EAC)h$;8WIR1rohQ#w444G0#1m$Dj66xet|L#R>4C36e7xMM0T)(aSAa2XfV)D zcEU#my$(kCaRx~QL^LgQ_;=)3gHxFOXBZJd{maEJLqY3H<>rDuET^1Yth7z0>+1gi X{l69U>r1pj4E?y3$fw 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 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftbrn2c08.png b/extern/libpng/include/contrib/pngsuite/ftbrn2c08.png new file mode 100644 index 0000000000000000000000000000000000000000..5cca0d621047cacf1637cf7d77e997d51cc6b15a GIT binary patch literal 1633 zcmV-n2A=teP))6_}Akuqmh*5X4X^rIbM;BH-v?$kU01p_ErCl=u4~ zL7fbz&H-~9!(}3aFu`RZW&unzb50QkgK2!RYsr=o3t~2tT^d3tzx&+X@9uj)%)Vj6 z{|IpB&Yj-g-pR?y{}^!Z-o3WAwzRagh=_<-fB!T`$I~7jJzDL9k&%A|7#|<+>gvkP z&5eqRQiO&cb#=`%Gt&SnAO*+-su`xq!J$j392p#Z_UzeG0aH^`SFc_zD=UkSkAGjG zNZGY3d;R({hG_tbfDeIqE;r1MUWVZftDkNW!h zs;jG$lamt?5{`w2W;;5Ta5(kAS>OWD3k(34fhLB@x3Eyz+ozkGX8`3uA)t^*Vq;_J zARVu%si6?50P_I-{r&0b>GXAy-pZYvJ_kMn+JSRiZt1pd#bWVg8=D~(>oza}`~v)> zM}7e)8HRFA`iDhFM^mix0K>z>DwQfHCnqyAGc`3;6%f#2ZhqFvO5^8uBq=H7FUwFU zT6XLhvbG*uwdz+cchJo2l$~8_P|)B15EmC05)$I?@88+kIS+9E{(W+tk&&UwQ56&v z(A`o(AH0rH_Tk~-0RaJGvDnww_wL=h^8j=?>6z)a6}IeCY}aO2b*Z|fq@=L0@WhD| zsSDdty^(jSiA*M&bM5WzEtks;bWvVj9&?GoHDC(zc6o7eG4)bKMMY_8X?Aw@u?6h# z;lshf`|a#hY<3Bkd&JHz$kWs3`0?Wg0OXPTF&CY{G^|Igi;9ZKH36!ss;DvOr&_J1 zx~1t&sZ>(M4;(lkk?c1!`x@w{b_L!AqU`OZt*xyF0OXE$lBa8(+d4*aQ!-UaQ=##! z_w+pDSx{e4UteEaTT3@Y0IErFaIj1kyl&n1z;8e!i?yF&L_nC8m3(Mu$N-?Zxp_n7 z2DAX*=>Wn$A?4)L>VvOzv*1+iR99Em(9l2wMRh0dROro{PXe>RH6x>UEG*vQa@TOV zQlU`t^yyOrfcExwL7@Om)cL>za2|4U%W^%=c<5%V3NB?X6h0+EjKsu5@-7xf85_?~ z_(n!?E-s$Cckkx$Tm=FtNq~V#ChO_xan5qaMSv9N2jF-3*7yqRh3Ek)Au1KoO;8fV zprIvzKyXeU{%KoVxrc`zkCz5CFib&h?McIcn>TN|Dcy8{RDkAq5^L3Kg|$LmUsXU< zBBJ4(W03sGWO5UeaSET!R&3c4%;9JOl9gkorlAz5VF1mVSE84$J}Q`0nqU|>1Di@4 ze5+F&_hR?T%1UBTp~Aw#cJ55qhku#R59RT^^+74-!fSSE~<7VgEJh?uUa0qm; z8Ez47t52=QkANEJ0t(=x^_iQy^73*TT0XxG7zGZwyYCSQ1YB+maEUU=$|_zAke{D# zTyIS3>>TO5U9}y3y6WrNG#}mt-ZU1(ApHmo3|zUggX&{s6zS#V<>Yh_y5_4hF$wDK z?p_S=`P`~WeyGw#>B+X26iZPz^D41kPE3=O0g4z6qf*N)=*PsGE4-+(Dp2{ zw2Zxeeeh*hh5=+_V`EuaSwV3@IIpj54kWn}jYdNZ8e`JrO`E(~ENUAnPWZ-+iMMY3 zY|zhwfLVQ0wY0S8#Df-Q7G&8n5<6nh7)vA)kx0bn+nAbqczMM?d^oX?lf?jYc4O#< zON|S4tujMN`;Hh?Jz7|PetuiGZY4pbYg^pItKUTv6B8tGw0Wp##Go?l literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftbwn1g16.png b/extern/libpng/include/contrib/pngsuite/ftbwn1g16.png new file mode 100644 index 0000000000000000000000000000000000000000..99bdeed2b3b8564302d449e6578c4aca0f6261f5 GIT binary patch literal 1313 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 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftp0n1g08.png b/extern/libpng/include/contrib/pngsuite/ftp0n1g08.png new file mode 100644 index 0000000000000000000000000000000000000000..333465fcdc9f10f7f25b2d999b558f5421983ecc GIT binary patch literal 719 zcmV;=0xe{x-64Dw5ISbDJfGPNXYF1fsnx~?7~M3eMD*m6rOMo0;2$rUW>-c(^**S*Ycd0zuX+u!1|S9WB+#F78QX<>lo? ziQz$h-hRnIWoQ!H=elq>2fX`s$g4Md}>$Ugu1e*ygBpcmqZ3DNb_5HNEsBtg8Fz$MsRgsRcUEt!R)#7 z@*=Hdg|%Ijgaqfp6x>M8@W|(*DezA>78ATBV zGiJ?6^pq7`pj8TmNNXtGQ7M(fr#kNOGpUKtO+a# zE}lAlTDXoRkAt?j2v0jgK~H>oU`AO)UQprWsr_L}qI~YALPA1E5ej}SPEJnGOv?!@ zojAEOR7Ob9QdC4?8%mP9keiy8ksVOlKd~`Xk)KCEK=mA2ntaoimYx|<+}mFjqR+?8 zZTJ8q(f(PLp6*}V-CGiDD=qBv7F)8vQWR0&(VZLQZ(jZjd%k$Tpt-FhJuqOwUu^jT z1pXapZA%Q=jx2U BP!RwC literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftp0n2c08.png b/extern/libpng/include/contrib/pngsuite/ftp0n2c08.png new file mode 100644 index 0000000000000000000000000000000000000000..fc6e42cb420fd08ecd78340256157fa5f8a22934 GIT binary patch literal 1594 zcmV-A2F3Y_P)u542F>)wJ;-zU<0Ta5X4X^rIbM; zBH-v?$kU01p_ErCl=u4~L7fbz&H-~9!(}3aFu`RZW&unzb50QkgK2zirzKlPEQpyV zJ88Z&UwhB*+;h+QpNot)Z1^7mZr{G$*Vi{SHT9YSckkY9Z*NaePmhd@j0*@zcXT}E z>DjB%+#enNPk@PuiSF+1yu7^V=xBLZ*b!IPd^0mOpafEZETD#AngxPxg<^DQ=;_m^ zO9f0%PhYumrM$d6AtB*?xjc2}&YX4Y${D5+CG4W_vSdOD(DVN&-oB_@QeZU}a320`R0!vG! zgF}Y7c_vT+6ajLvI4&-Z7Si(C+FA;c5-<-iFfc$*`Z-x=6;4i{1D^pMz*&|p+q$(x zB)Vj4J8WQZ3z!6c0e;dUzW@{rLwimBm&L@yP^|L+BO@b9r7|}+H!CYEEiFwM7}#lU ze#Y8b?eBj$IXU%j%aqGow{IV|u^C^v@>iA}GBZ1AZ=V(%{LdfavLmWItxn1d>CixU>w z(z&H&q%@~cmeiGMuLdu#(_V!Qg$)f2b#--gLIj|kgoK1hr6FtAeh>TxG#MD|V;DCe z+}c_;JUpxi(9+VfzG^*Mf$y{cVZV^}t ze*#wx4d1b}e2ZmQv#dlY6hC?LL=T{&qk~_>M>ADEa39m2fL{qvo7rko-xdG82;t3ZKJ~Z{8fjKg!o$ON?8wlCe~HHnv#{{d1tq7Cl~vHp z%#3~jNv`NUkyhKvAxIVA8=wbFDWm}$)k06v92)E2}b{Rj#QTCt*&@?&Ti zD zl4Z+2B9B~dgtK!fhf@n&;PLjfw||-Og6SEVLqkKcv9UCP1w{gUs+$RUkfbMoF`VR)x@ASCQaVB z(Z|4m%7&5?v0+2f&6_{#^|K%#LswL-t*u(|pn;hUX^xb{ju_O&VzJoG&5g&iH8u70 z_D*>4U~(ZRivi~B`tWs^S{JHXMW%x09Wf|-G_d^r{kLq{LV`-iwz!9v--{+ECrRLF z@=(%OV07*qoM6N<$f`h#14gdfE literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftp0n3p08.png b/extern/libpng/include/contrib/pngsuite/ftp0n3p08.png new file mode 100644 index 0000000000000000000000000000000000000000..69a69e5872234d96cab4cbb017a0933fbfedba81 GIT binary patch literal 1476 zcmWlXc~H^`6vv-Om}J3dn5OOMOgg5aIm=3#R_~R8*9gm+#ueDlIJqsFg@0;tH{|b8}HqQ5Jw$Ebasl zi9{wQqx{s={QP`?_T1du%K+m5+1c6W&Yc6O&&;#KYi za0xyG{0*U@p&=n5OeT{~rxS7s!NI{ht9Awk26}jqu-LA432IQH$P*->1%a<=E7fhf7KmpiNEL?|$g$1|@ z&=;ZU0fm$KWEP7BFz+mN_CD$D>KXyBfJUPQ1qHz$U@Noz`t>V3 z0Y5*#_4Rf5=AAr|%l))v3zbTRZXmD;`udA>dIa18XhRr(3s9%iK@&&<11kswKn|(| zCKfuzi4TRu*jp4GWDgcp#{666_U|?<$;@lL6fyrT=v@~MF43;U zZ$6b_)kkb?TQRlFx@L1DFHuvCdiGRV@qSb5o3SyX=dqWIo~SD}lgtU8-0hinIc|l^ zwZpyIy{+Kp3qku~jyuQS{wOJTffqk}ylg!rGf@@8WYp~qRTEe@i_6M#f}U2WR@4MfM)1HJRjPCMx~ z7uM(-p3*y>&A)fhi1A3;cS(L+J1;&pqWL&it>CX0-+eBqO{=g-lKzNGvG(`sNqtRF zeg3%mDzvL|F3Eho_0DyETn8H%dc!?dA!#0>Q=Vr9#{-Ga&|1#6CAW+Q0sfY$`N-&; z^0c=#@%4)8jy6X3lL6u3JAW=?c#tm>K2a$#(Q?|Uz}T^+pWADD@MB|q8>&Xr948aj zsY1|Z7&ad@u4wr4W%TE{WS7U&Rh^yI#(OsCtq$vQ3|A*M_uLm%-A~M)I@BiVUyS#YR$&g!`CNx58tIE z|3D@=NLJY$Q%;J12ZU?1w#&^2c5EzDN05DZLoa2szJ*SEwwg0|Mem<$Yn1cWcz^cq z-}lxrB6iz%k1R&3=>`|KS%};k)l(YskH!jI!g#-(&O>3hx)5(GX8X3fe_&q16?&Zr z)72bEymR&OySDOI3mZ0C3tSEiO=8X3u^BG}uBukDWrMyZ$LQ%Y4sr7@il=hRi%!IK N0G~qvls0mN@PBi2fm#3n literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/pngsuite/ftp1n3p08.png b/extern/libpng/include/contrib/pngsuite/ftp1n3p08.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c9f35a86271c056e955f637a8769381eb03827 GIT binary patch literal 1483 zcmWlXdpOez7{_0ijw~Xj6ZLfH5mEEBP|@KrEtkTuS}m>SI;>1?8{6D(v$V!$$}kk^ z;zXQM92O%H=ShmnbXw(ZQ8_r3^Xq+{_x=9)zVGMz<@$KL>7tBL0HEvPj`Ks*k)Uu?Q@xn6z>Z3lMM-Q#6tfUZ$jg9xOySS8oYSdsZ?58S}Ku90Gh5`xl#{MR8%wt zP*_-43Lq2;*RS7_pPzr}(xrd%E)}>Vg+~H{0|EmB;S209 z+JEZQsgoy9!bij)vJ2CNNF)M$vKCsqg}Grc6c_?OKR+KIALs+qBGU~U&cS2w^z{7x z{X6{3T?w5=n_Ror-Q69U!8X)ZUHvP8K!G~|wFu*%2C7slr~p15FS4}-9)W zgA1TkDj@~(fB8jCjUG%S0R(${)B5}SM@HTPu)4duH*Un5nj+Sda5!dbYwOg=2pWA9 zg`xngv~oCl+wa{*R;b1Lc@x0-<4`CPvRn@w_UQh+Ac}Mk^OKb>f7-E19*W;}xs}~! zRlIciNyF__FM9f7*5I)-+cbPa1|k-TrQvsONlsb*)pnz$h0|UcNA3@z)MNfwE}Uv0 zIbFH+_Zk14HEp3y&g@1-ft^E-J#CK+WhE5TXruYlt&^-N^P3g#I=H!w`R}L=sT9s{ zCuD1uhCdG)aY*zhVd3F}HZMyY{g2C62iLwz8h1Q_?PFhSvbid>^O4P?YqRlh((eZd z#_aspCH=EBx%*CRO=qIG-J;L_AlZKBgiu)@&Tb|Ii=AapW?Zqp>gYA)sH#J5XB+h; zk9wYVqsyC_bvIrV9&w7WX>VWUAVpP~na{j&$UYNXX^m&}Uyx5RnnjA&4L3VdD!1H_ zD#Iq{ZueA8l;TIb`kpn$X5SsBHj?FpV!HrYcY~@^RN}pDGk;X^V&G~0qorYaOP*rv z^qN~4t3n!C(Ta6lUVkRto3S5$_!4xZm;=Uxwl-UlXk<^TD! zwrXx-kZ%7r>OqrnxrwlgbC>i*G{g?VCRx6GHc+-!v-|w+aMq(Z)3<$!sgDrNgW zt{66;txYft&kQV}Qtm74k`-qO{C2WMU5|#0wUn?oyC~|ghKx56YPk5`Xp_O#x8g2M X(5+n&l!#upArS?SL*BSr7fRay;V71Q literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/visupng/PngFile.c b/extern/libpng/include/contrib/visupng/PngFile.c new file mode 100644 index 0000000000..db0219e35e --- /dev/null +++ b/extern/libpng/include/contrib/visupng/PngFile.c @@ -0,0 +1,442 @@ +//------------------------------------- +// PNGFILE.C -- Image File Functions +//------------------------------------- + +// Copyright 2000, Willem van Schaik. +// +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +#include +#include +#include +#include + +#include "png.h" +#include "pngfile.h" +#include "cexcept.h" + +define_exception_type(const char *); +extern struct exception_context the_exception_context[1]; +struct exception_context the_exception_context[1]; +png_const_charp msg; + +static OPENFILENAME ofn; + +static png_structp png_ptr = NULL; +static png_infop info_ptr = NULL; + + +// cexcept interface + +static void +png_cexcept_error(png_structp png_ptr, png_const_charp msg) +{ + if(png_ptr) + ; +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "libpng error: %s\n", msg); +#endif + { + Throw msg; + } +} + +// Windows open-file functions + +void PngFileInitialize (HWND hwnd) +{ + static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0") + TEXT ("All Files (*.*)\0*.*\0\0"); + + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.hwndOwner = hwnd; + ofn.hInstance = NULL; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 0; + ofn.lpstrFile = NULL; // Set in Open and Close functions + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = NULL; // Set in Open and Close functions + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = NULL; + ofn.Flags = 0; // Set in Open and Close functions + ofn.nFileOffset = 0; + ofn.nFileExtension = 0; + ofn.lpstrDefExt = TEXT ("png"); + ofn.lCustData = 0; + ofn.lpfnHook = NULL; + ofn.lpTemplateName = NULL; +} + +BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) +{ + ofn.hwndOwner = hwnd; + ofn.lpstrFile = pstrFileName; + ofn.lpstrFileTitle = pstrTitleName; + ofn.Flags = OFN_HIDEREADONLY; + + return GetOpenFileName (&ofn); +} + +BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) +{ + ofn.hwndOwner = hwnd; + ofn.lpstrFile = pstrFileName; + ofn.lpstrFileTitle = pstrTitleName; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + + return GetSaveFileName (&ofn); +} + +// PNG image handler functions + +BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData, + int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor) +{ + static FILE *pfFile; + png_byte pbSig[8]; + int iBitDepth; + int iColorType; + double dGamma; + png_color_16 *pBackground; + png_uint_32 ulChannels; + png_uint_32 ulRowBytes; + png_byte *pbImageData = *ppbImageData; + static png_byte **ppbRowPointers = NULL; + int i; + + // open the PNG input file + + if (!pstrFileName) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + if (!(pfFile = fopen(pstrFileName, "rb"))) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + // first check the eight byte PNG signature + + fread(pbSig, 1, 8, pfFile); + if (png_sig_cmp(pbSig, 0, 8)) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + // create the two png(-info) structures + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); + if (!png_ptr) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + Try + { + + // initialize the png structure + +#ifdef PNG_STDIO_SUPPORTED + png_init_io(png_ptr, pfFile); +#else + png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data); +#endif + + png_set_sig_bytes(png_ptr, 8); + + // read all PNG info up to image data + + png_read_info(png_ptr, info_ptr); + + // get width, height, bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, + &iColorType, NULL, NULL, NULL); + + // expand images of all color-type and bit-depth to 3x8 bit RGB images + // let the library process things like alpha, transparency, background + + if (iBitDepth == 16) + png_set_strip_16(png_ptr); + if (iColorType == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (iBitDepth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (iColorType == PNG_COLOR_TYPE_GRAY || + iColorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + // set the background color to draw transparent and alpha images over. + if (png_get_bKGD(png_ptr, info_ptr, &pBackground)) + { + png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + pBkgColor->red = (byte) pBackground->red; + pBkgColor->green = (byte) pBackground->green; + pBkgColor->blue = (byte) pBackground->blue; + } + else + { + pBkgColor = NULL; + } + + // if required set gamma conversion + if (png_get_gAMA(png_ptr, info_ptr, &dGamma)) + png_set_gamma(png_ptr, (double) 2.2, dGamma); + + // after the transformations have been registered update info_ptr data + + png_read_update_info(png_ptr, info_ptr); + + // get again width, height and the new bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, + &iColorType, NULL, NULL, NULL); + + + // row_bytes is the width x number of channels + + ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); + ulChannels = png_get_channels(png_ptr, info_ptr); + + *piChannels = ulChannels; + + // now we can allocate memory to store the image + + if (pbImageData) + { + free (pbImageData); + pbImageData = NULL; + } + if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight) + * sizeof(png_byte))) == NULL) + { + png_error(png_ptr, "Visual PNG: out of memory"); + } + *ppbImageData = pbImageData; + + // and allocate memory for an array of row-pointers + + if ((ppbRowPointers = (png_bytepp) malloc((*piHeight) + * sizeof(png_bytep))) == NULL) + { + png_error(png_ptr, "Visual PNG: out of memory"); + } + + // set the individual row-pointers to point at the correct offsets + + for (i = 0; i < (*piHeight); i++) + ppbRowPointers[i] = pbImageData + i * ulRowBytes; + + // now we can go ahead and just read the whole image + + png_read_image(png_ptr, ppbRowPointers); + + // read the additional chunks in the PNG file (not really needed) + + png_read_end(png_ptr, NULL); + + // and we're done + + free (ppbRowPointers); + ppbRowPointers = NULL; + + // yepp, done + } + + Catch (msg) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + *ppbImageData = pbImageData = NULL; + + if(ppbRowPointers) + free (ppbRowPointers); + + fclose(pfFile); + + return FALSE; + } + + fclose (pfFile); + + return TRUE; +} + + +BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData, + int iWidth, int iHeight, png_color bkgColor) +{ + const int ciBitDepth = 8; + const int ciChannels = 3; + + static FILE *pfFile; + png_uint_32 ulRowBytes; + static png_byte **ppbRowPointers = NULL; + int i; + + // open the PNG output file + + if (!pstrFileName) + return FALSE; + + if (!(pfFile = fopen(pstrFileName, "wb"))) + return FALSE; + + // prepare the standard PNG structures + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, + (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); + if (!png_ptr) + { + fclose(pfFile); + return FALSE; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fclose(pfFile); + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + Try + { + // initialize the png structure + +#ifdef PNG_STDIO_SUPPORTED + png_init_io(png_ptr, pfFile); +#else + png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush); +#endif + + // we're going to write a very simple 3x8 bit RGB image + + png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + // write the file header information + + png_write_info(png_ptr, info_ptr); + + // swap the BGR pixels in the DiData structure to RGB + + png_set_bgr(png_ptr); + + // row_bytes is the width x number of channels + + ulRowBytes = iWidth * ciChannels; + + // we can allocate memory for an array of row-pointers + + if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL) + Throw "Visualpng: Out of memory"; + + // set the individual row-pointers to point at the correct offsets + + for (i = 0; i < iHeight; i++) + ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2); + + // write out the entire image data in one call + + png_write_image (png_ptr, ppbRowPointers); + + // write the additional chunks to the PNG file (not really needed) + + png_write_end(png_ptr, info_ptr); + + // and we're done + + free (ppbRowPointers); + ppbRowPointers = NULL; + + // clean up after the write, and free any memory allocated + + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + + // yepp, done + } + + Catch (msg) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + + if(ppbRowPointers) + free (ppbRowPointers); + + fclose(pfFile); + + return FALSE; + } + + fclose (pfFile); + + return TRUE; +} + +#ifndef PNG_STDIO_SUPPORTED + +static void +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = (png_size_t)fread(data, (png_size_t)1, length, + (FILE *)png_ptr->io_ptr); + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } +} + +static void +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} + +static void +png_flush(png_structp png_ptr) +{ + FILE *io_ptr; + io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +} + +#endif + +//----------------- +// end of source +//----------------- diff --git a/extern/libpng/include/contrib/visupng/PngFile.h b/extern/libpng/include/contrib/visupng/PngFile.h new file mode 100644 index 0000000000..dc6bbb409f --- /dev/null +++ b/extern/libpng/include/contrib/visupng/PngFile.h @@ -0,0 +1,30 @@ +//------------------------------------------ +// PNGFILE.H -- Header File for pngfile.c +//------------------------------------------ + +// Copyright 2000, Willem van Schaik. + +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +#include +#include +#include +#include + +void PngFileInitialize (HWND hwnd) ; +BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ; +BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ; + +BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData, + int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor); +BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData, + int iWidth, int iHeight, png_color BkgColor); + +#ifndef PNG_STDIO_SUPPORTED +static void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void png_flush(png_structp png_ptr); +#endif + diff --git a/extern/libpng/include/contrib/visupng/README.txt b/extern/libpng/include/contrib/visupng/README.txt new file mode 100644 index 0000000000..4047119a58 --- /dev/null +++ b/extern/libpng/include/contrib/visupng/README.txt @@ -0,0 +1,61 @@ +Microsoft Developer Studio Build File, Format Version 6.00 for VisualPng +------------------------------------------------------------------------ + +Copyright 2000, Willem van Schaik. + +This code is released under the libpng license. +For conditions of distribution and use, see the disclaimer +and license in png.h + +As a PNG .dll demo VisualPng is finished. More features would only hinder +the program's objective. However, further extensions (like support for other +graphics formats) are in development. To get these, or for pre-compiled +binaries, go to "http://www.schaik.com/png/visualpng.html". + +------------------------------------------------------------------------ + +Assumes that + + libpng DLLs and LIBs are in ..\..\projects\msvc\win32\libpng + zlib DLLs and LIBs are in ..\..\projects\msvc\win32\zlib + libpng header files are in ..\..\..\libpng + zlib header files are in ..\..\..\zlib + the pngsuite images are in ..\pngsuite + +To build: + +1) On the main menu Select "Build|Set Active configuration". + Choose the configuration that corresponds to the library you want to test. + This library must have been built using the libpng MS project located in + the "..\..\mscv" subdirectory. + +2) Select "Build|Clean" + +3) Select "Build|Rebuild All" + +4) After compiling and linking VisualPng will be started to view an image + from the PngSuite directory. Press Ctrl-N (and Ctrl-V) for other images. + + +To install: + +When distributing VisualPng (or a further development) the following options +are available: + +1) Build the program with the configuration "Win32 LIB" and you only need to + include the executable from the ./lib directory in your distribution. + +2) Build the program with the configuration "Win32 DLL" and you need to put + in your distribution the executable from the ./dll directory and the dll's + libpng1.dll, zlib.dll and msvcrt.dll. These need to be in the user's PATH. + + +Willem van Schaik +Calgary, June 6th 2000 + +P.S. VisualPng was written based on preliminary work of: + + - Simon-Pierre Cadieux + - Glenn Randers-Pehrson + - Greg Roelofs + diff --git a/extern/libpng/include/contrib/visupng/VisualPng.c b/extern/libpng/include/contrib/visupng/VisualPng.c new file mode 100644 index 0000000000..2018999a05 --- /dev/null +++ b/extern/libpng/include/contrib/visupng/VisualPng.c @@ -0,0 +1,964 @@ +//------------------------------------ +// VisualPng.C -- Shows a PNG image +//------------------------------------ + +// Copyright 2000, Willem van Schaik. + +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +// switches + +// defines + +#define PROGNAME "VisualPng" +#define LONGNAME "Win32 Viewer for PNG-files" +#define VERSION "1.0 of 2000 June 07" + +// constants + +#define MARGIN 8 + +// standard includes + +#include +#include +#include +#include + +// application includes + +#include "png.h" +#include "pngfile.h" +#include "resource.h" + +// macros + +// function prototypes + +LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ; + +BOOL CenterAbout (HWND hwndChild, HWND hwndParent); + +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount, + int *pFileIndex); + +BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex, + PTSTR pstrPrevName, PTSTR pstrNextName); + +BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName, + png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels, + png_color *pBkgColor); + +BOOL DisplayImage (HWND hwnd, BYTE **ppDib, + BYTE **ppDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched); + +BOOL InitBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize); + +BOOL FillBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched); + +// a few global variables + +static char *szProgName = PROGNAME; +static char *szAppName = LONGNAME; +static char *szIconName = PROGNAME; +static char szCmdFileName [MAX_PATH]; + +// MAIN routine + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + PSTR szCmdLine, int iCmdShow) +{ + HACCEL hAccel; + HWND hwnd; + MSG msg; + WNDCLASS wndclass; + int ixBorders, iyBorders; + + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon (hInstance, szIconName) ; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = NULL; // (HBRUSH) GetStockObject (GRAY_BRUSH); + wndclass.lpszMenuName = szProgName; + wndclass.lpszClassName = szProgName; + + if (!RegisterClass (&wndclass)) + { + MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"), + szProgName, MB_ICONERROR); + return 0; + } + + // if filename given on commandline, store it + if ((szCmdLine != NULL) && (*szCmdLine != '\0')) + if (szCmdLine[0] == '"') + strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2); + else + strcpy (szCmdFileName, szCmdLine); + else + strcpy (szCmdFileName, ""); + + // calculate size of window-borders + ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) + + GetSystemMetrics (SM_CXDLGFRAME)); + iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) + + GetSystemMetrics (SM_CYDLGFRAME)) + + GetSystemMetrics (SM_CYCAPTION) + + GetSystemMetrics (SM_CYMENUSIZE) + + 1; /* WvS: don't ask me why? */ + + hwnd = CreateWindow (szProgName, szAppName, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders, +// CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); + + ShowWindow (hwnd, iCmdShow); + UpdateWindow (hwnd); + + hAccel = LoadAccelerators (hInstance, szProgName); + + while (GetMessage (&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator (hwnd, hAccel, &msg)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + return msg.wParam; +} + +LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) +{ + static HINSTANCE hInstance ; + static HDC hdc; + static PAINTSTRUCT ps; + static HMENU hMenu; + + static BITMAPFILEHEADER *pbmfh; + static BITMAPINFOHEADER *pbmih; + static BYTE *pbImage; + static int cxWinSize, cyWinSize; + static int cxImgSize, cyImgSize; + static int cImgChannels; + static png_color bkgColor = {127, 127, 127}; + + static BOOL bStretched = TRUE; + + static BYTE *pDib = NULL; + static BYTE *pDiData = NULL; + + static TCHAR szImgPathName [MAX_PATH]; + static TCHAR szTitleName [MAX_PATH]; + + static TCHAR *pPngFileList = NULL; + static int iPngFileCount; + static int iPngFileIndex; + + BOOL bOk; + + switch (message) + { + case WM_CREATE: + hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; + PngFileInitialize (hwnd); + + strcpy (szImgPathName, ""); + + // in case we process file given on command-line + + if (szCmdFileName[0] != '\0') + { + strcpy (szImgPathName, szCmdFileName); + + // read the other png-files in the directory for later + // next/previous commands + + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, + &iPngFileIndex); + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case WM_SIZE: + cxWinSize = LOWORD (lParam); + cyWinSize = HIWORD (lParam); + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case WM_INITMENUPOPUP: + hMenu = GetMenu (hwnd); + + if (pbImage) + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED); + else + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED); + + return 0; + + case WM_COMMAND: + hMenu = GetMenu (hwnd); + + switch (LOWORD (wParam)) + { + case IDM_FILE_OPEN: + + // show the File Open dialog box + + if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName)) + return 0; + + // read the other png-files in the directory for later + // next/previous commands + + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, + &iPngFileIndex); + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case IDM_FILE_SAVE: + + // show the File Save dialog box + + if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName)) + return 0; + + // save the PNG to a disk file + + SetCursor (LoadCursor (NULL, IDC_WAIT)); + ShowCursor (TRUE); + + bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize, + bkgColor); + + ShowCursor (FALSE); + SetCursor (LoadCursor (NULL, IDC_ARROW)); + + if (!bOk) + MessageBox (hwnd, TEXT ("Error in saving the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + return 0; + + case IDM_FILE_NEXT: + + // read next entry in the directory + + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, + NULL, szImgPathName)) + { + if (strcmp (szImgPathName, "") == 0) + return 0; + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, &pbImage, + &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case IDM_FILE_PREVIOUS: + + // read previous entry in the directory + + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, + szImgPathName, NULL)) + { + + if (strcmp (szImgPathName, "") == 0) + return 0; + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize, + &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case IDM_FILE_EXIT: + + // more cleanup needed... + + // free image buffer + + if (pDib != NULL) + { + free (pDib); + pDib = NULL; + } + + // free file-list + + if (pPngFileList != NULL) + { + free (pPngFileList); + pPngFileList = NULL; + } + + // let's go ... + + exit (0); + + return 0; + + case IDM_OPTIONS_STRETCH: + bStretched = !bStretched; + if (bStretched) + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED); + else + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED); + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case IDM_HELP_ABOUT: + DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ; + return 0; + + } // end switch + + break; + + case WM_PAINT: + hdc = BeginPaint (hwnd, &ps); + + if (pDib) + SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0, + 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS); + + EndPaint (hwnd, &ps); + return 0; + + case WM_DESTROY: + if (pbmfh) + { + free (pbmfh); + pbmfh = NULL; + } + + PostQuitMessage (0); + return 0; + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} + +BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG : + ShowWindow (hDlg, SW_HIDE); + CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER)); + ShowWindow (hDlg, SW_SHOW); + return TRUE ; + + case WM_COMMAND : + switch (LOWORD (wParam)) + { + case IDOK : + case IDCANCEL : + EndDialog (hDlg, 0) ; + return TRUE ; + } + break ; + } + return FALSE ; +} + +//--------------- +// CenterAbout +//--------------- + +BOOL CenterAbout (HWND hwndChild, HWND hwndParent) +{ + RECT rChild, rParent, rWorkArea; + int wChild, hChild, wParent, hParent; + int xNew, yNew; + BOOL bResult; + + // Get the Height and Width of the child window + GetWindowRect (hwndChild, &rChild); + wChild = rChild.right - rChild.left; + hChild = rChild.bottom - rChild.top; + + // Get the Height and Width of the parent window + GetWindowRect (hwndParent, &rParent); + wParent = rParent.right - rParent.left; + hParent = rParent.bottom - rParent.top; + + // Get the limits of the 'workarea' + bResult = SystemParametersInfo( + SPI_GETWORKAREA, // system parameter to query or set + sizeof(RECT), + &rWorkArea, + 0); + if (!bResult) { + rWorkArea.left = rWorkArea.top = 0; + rWorkArea.right = GetSystemMetrics(SM_CXSCREEN); + rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN); + } + + // Calculate new X position, then adjust for workarea + xNew = rParent.left + ((wParent - wChild) /2); + if (xNew < rWorkArea.left) { + xNew = rWorkArea.left; + } else if ((xNew+wChild) > rWorkArea.right) { + xNew = rWorkArea.right - wChild; + } + + // Calculate new Y position, then adjust for workarea + yNew = rParent.top + ((hParent - hChild) /2); + if (yNew < rWorkArea.top) { + yNew = rWorkArea.top; + } else if ((yNew+hChild) > rWorkArea.bottom) { + yNew = rWorkArea.bottom - hChild; + } + + // Set it, and return + return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | + SWP_NOZORDER); +} + +//---------------- +// BuildPngList +//---------------- + +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount, + int *pFileIndex) +{ + static TCHAR szImgPathName [MAX_PATH]; + static TCHAR szImgFileName [MAX_PATH]; + static TCHAR szImgFindName [MAX_PATH]; + + WIN32_FIND_DATA finddata; + HANDLE hFind; + + static TCHAR szTmp [MAX_PATH]; + BOOL bOk; + int i, ii; + int j, jj; + + // free previous file-list + + if (*ppFileList != NULL) + { + free (*ppFileList); + *ppFileList = NULL; + } + + // extract foldername, filename and search-name + + strcpy (szImgPathName, pstrPathName); + strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1); + + strcpy (szImgFindName, szImgPathName); + *(strrchr (szImgFindName, '\\') + 1) = '\0'; + strcat (szImgFindName, "*.png"); + + // first cycle: count number of files in directory for memory allocation + + *pFileCount = 0; + + hFind = FindFirstFile(szImgFindName, &finddata); + bOk = (hFind != (HANDLE) -1); + + while (bOk) + { + *pFileCount += 1; + bOk = FindNextFile(hFind, &finddata); + } + FindClose(hFind); + + // allocation memory for file-list + + *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH); + + // second cycle: read directory and store filenames in file-list + + hFind = FindFirstFile(szImgFindName, &finddata); + bOk = (hFind != (HANDLE) -1); + + i = 0; + ii = 0; + while (bOk) + { + strcpy (*ppFileList + ii, szImgPathName); + strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName); + + if (strcmp(pstrPathName, *ppFileList + ii) == 0) + *pFileIndex = i; + + ii += MAX_PATH; + i++; + + bOk = FindNextFile(hFind, &finddata); + } + FindClose(hFind); + + // finally we must sort the file-list + + for (i = 0; i < *pFileCount - 1; i++) + { + ii = i * MAX_PATH; + for (j = i+1; j < *pFileCount; j++) + { + jj = j * MAX_PATH; + if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0) + { + strcpy (szTmp, *ppFileList + jj); + strcpy (*ppFileList + jj, *ppFileList + ii); + strcpy (*ppFileList + ii, szTmp); + + // check if this was the current image that we moved + + if (*pFileIndex == i) + *pFileIndex = j; + else + if (*pFileIndex == j) + *pFileIndex = i; + } + } + } + + return TRUE; +} + +//---------------- +// SearchPngList +//---------------- + +BOOL SearchPngList ( + TCHAR *pFileList, int FileCount, int *pFileIndex, + PTSTR pstrPrevName, PTSTR pstrNextName) +{ + if (FileCount > 0) + { + // get previous entry + + if (pstrPrevName != NULL) + { + if (*pFileIndex > 0) + *pFileIndex -= 1; + else + *pFileIndex = FileCount - 1; + + strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH)); + } + + // get next entry + + if (pstrNextName != NULL) + { + if (*pFileIndex < FileCount - 1) + *pFileIndex += 1; + else + *pFileIndex = 0; + + strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH)); + } + + return TRUE; + } + else + { + return FALSE; + } +} + +//----------------- +// LoadImageFile +//----------------- + +BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName, + png_byte **ppbImage, int *pxImgSize, int *pyImgSize, + int *piChannels, png_color *pBkgColor) +{ + static TCHAR szTmp [MAX_PATH]; + + // if there's an existing PNG, free the memory + + if (*ppbImage) + { + free (*ppbImage); + *ppbImage = NULL; + } + + // Load the entire PNG into memory + + SetCursor (LoadCursor (NULL, IDC_WAIT)); + ShowCursor (TRUE); + + PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels, + pBkgColor); + + ShowCursor (FALSE); + SetCursor (LoadCursor (NULL, IDC_ARROW)); + + if (*ppbImage != NULL) + { + sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1); + SetWindowText (hwnd, szTmp); + } + else + { + MessageBox (hwnd, TEXT ("Error in loading the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + return FALSE; + } + + return TRUE; +} + +//---------------- +// DisplayImage +//---------------- + +BOOL DisplayImage (HWND hwnd, BYTE **ppDib, + BYTE **ppDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched) +{ + BYTE *pDib = *ppDib; + BYTE *pDiData = *ppDiData; + // BITMAPFILEHEADER *pbmfh; + BITMAPINFOHEADER *pbmih; + WORD wDIRowBytes; + png_color bkgBlack = {0, 0, 0}; + png_color bkgGray = {127, 127, 127}; + png_color bkgWhite = {255, 255, 255}; + + // allocate memory for the Device Independant bitmap + + wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2; + + if (pDib) + { + free (pDib); + pDib = NULL; + } + + if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) + + wDIRowBytes * cyWinSize))) + { + MessageBox (hwnd, TEXT ("Error in displaying the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + *ppDib = pDib = NULL; + return FALSE; + } + *ppDib = pDib; + memset (pDib, 0, sizeof(BITMAPINFOHEADER)); + + // initialize the dib-structure + + pbmih = (BITMAPINFOHEADER *) pDib; + pbmih->biSize = sizeof(BITMAPINFOHEADER); + pbmih->biWidth = cxWinSize; + pbmih->biHeight = -((long) cyWinSize); + pbmih->biPlanes = 1; + pbmih->biBitCount = 24; + pbmih->biCompression = 0; + pDiData = pDib + sizeof(BITMAPINFOHEADER); + *ppDiData = pDiData; + + // first fill bitmap with gray and image border + + InitBitmap (pDiData, cxWinSize, cyWinSize); + + // then fill bitmap with image + + if (pbImage) + { + FillBitmap ( + pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, + bStretched); + } + + return TRUE; +} + +//-------------- +// InitBitmap +//-------------- + +BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize) +{ + BYTE *dst; + int x, y, col; + + // initialize the background with gray + + dst = pDiData; + for (y = 0; y < cyWinSize; y++) + { + col = 0; + for (x = 0; x < cxWinSize; x++) + { + // fill with GRAY + *dst++ = 127; + *dst++ = 127; + *dst++ = 127; + col += 3; + } + // rows start on 4 byte boundaries + while ((col % 4) != 0) + { + dst++; + col++; + } + } + + return TRUE; +} + +//-------------- +// FillBitmap +//-------------- + +BOOL FillBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched) +{ + BYTE *pStretchedImage; + BYTE *pImg; + BYTE *src, *dst; + BYTE r, g, b, a; + const int cDIChannels = 3; + WORD wImgRowBytes; + WORD wDIRowBytes; + int cxNewSize, cyNewSize; + int cxImgPos, cyImgPos; + int xImg, yImg; + int xWin, yWin; + int xOld, yOld; + int xNew, yNew; + + if (bStretched) + { + cxNewSize = cxWinSize - 2 * MARGIN; + cyNewSize = cyWinSize - 2 * MARGIN; + + // stretch the image to it's window determined size + + // the following two are the same, but the first has side-effects + // because of rounding +// if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) + if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize)) + { + cyNewSize = cxNewSize * cyImgSize / cxImgSize; + cxImgPos = MARGIN; + cyImgPos = (cyWinSize - cyNewSize) / 2; + } + else + { + cxNewSize = cyNewSize * cxImgSize / cyImgSize; + cyImgPos = MARGIN; + cxImgPos = (cxWinSize - cxNewSize) / 2; + } + + pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize); + pImg = pStretchedImage; + + for (yNew = 0; yNew < cyNewSize; yNew++) + { + yOld = yNew * cyImgSize / cyNewSize; + for (xNew = 0; xNew < cxNewSize; xNew++) + { + xOld = xNew * cxImgSize / cxNewSize; + + r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0); + g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1); + b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2); + *pImg++ = r; + *pImg++ = g; + *pImg++ = b; + if (cImgChannels == 4) + { + a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + + 3); + *pImg++ = a; + } + } + } + + // calculate row-bytes + + wImgRowBytes = cImgChannels * cxNewSize; + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; + + // copy image to screen + + for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++) + { + if (yWin >= cyWinSize - cyImgPos) + break; + src = pStretchedImage + yImg * wImgRowBytes; + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; + + for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++) + { + if (xWin >= cxWinSize - cxImgPos) + break; + r = *src++; + g = *src++; + b = *src++; + *dst++ = b; /* note the reverse order */ + *dst++ = g; + *dst++ = r; + if (cImgChannels == 4) + { + a = *src++; + } + } + } + + // free memory + + if (pStretchedImage != NULL) + { + free (pStretchedImage); + pStretchedImage = NULL; + } + + } + + // process the image not-stretched + + else + { + // calculate the central position + + cxImgPos = (cxWinSize - cxImgSize) / 2; + cyImgPos = (cyWinSize - cyImgSize) / 2; + + // check for image larger than window + + if (cxImgPos < MARGIN) + cxImgPos = MARGIN; + if (cyImgPos < MARGIN) + cyImgPos = MARGIN; + + // calculate both row-bytes + + wImgRowBytes = cImgChannels * cxImgSize; + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; + + // copy image to screen + + for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++) + { + if (yWin >= cyWinSize - MARGIN) + break; + src = pbImage + yImg * wImgRowBytes; + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; + + for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++) + { + if (xWin >= cxWinSize - MARGIN) + break; + r = *src++; + g = *src++; + b = *src++; + *dst++ = b; /* note the reverse order */ + *dst++ = g; + *dst++ = r; + if (cImgChannels == 4) + { + a = *src++; + } + } + } + } + + return TRUE; +} + +//----------------- +// end of source +//----------------- diff --git a/extern/libpng/include/contrib/visupng/VisualPng.dsp b/extern/libpng/include/contrib/visupng/VisualPng.dsp new file mode 100644 index 0000000000..741ef6ce76 --- /dev/null +++ b/extern/libpng/include/contrib/visupng/VisualPng.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="VisualPng" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=VisualPng - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "VisualPng.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "VisualPng.mak" CFG="VisualPng - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "VisualPng - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "VisualPng - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "VisualPng - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /O2 /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "NDEBUG" /D "PNG_NO_STDIO" /FD /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MD /W3 /O2 /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "NDEBUG" /D "PNG_NO_STDIO" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 ..\..\projects\visualc6\Win32_LIB_Release\libpng.lib ..\..\..\zlib\projects\visualc6\Win32_LIB_Release\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# Begin Special Build Tool +OutDir=.\Release +SOURCE="$(InputPath)" +PostBuild_Cmds=$(outdir)\VisualPng.exe ..\..\contrib\pngsuite\basn6a16.png +# End Special Build Tool + +!ELSEIF "$(CFG)" == "VisualPng - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "_DEBUG" /D "PNG_NO_STDIO" /FD /GZ /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "_DEBUG" /D "PNG_NO_STDIO" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ..\..\projects\visualc6\Win32_LIB_Release\libpng.lib ..\..\..\zlib\projects\visualc6\Win32_LIB_Release\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept +# Begin Special Build Tool +OutDir=.\Debug +SOURCE="$(InputPath)" +PostBuild_Cmds=$(outdir)\VisualPng.exe ..\..\contrib\pngsuite\basn6a16.png +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "VisualPng - Win32 Release" +# Name "VisualPng - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\PngFile.c +# End Source File +# Begin Source File + +SOURCE=.\VisualPng.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\cexcept.h +# End Source File +# Begin Source File + +SOURCE=.\PngFile.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\VisualPng.ico +# End Source File +# Begin Source File + +SOURCE=.\VisualPng.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/extern/libpng/include/contrib/visupng/VisualPng.dsw b/extern/libpng/include/contrib/visupng/VisualPng.dsw new file mode 100644 index 0000000000..a30e1cc1cd --- /dev/null +++ b/extern/libpng/include/contrib/visupng/VisualPng.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "VisualPng"=.\VisualPng.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/extern/libpng/include/contrib/visupng/VisualPng.ico b/extern/libpng/include/contrib/visupng/VisualPng.ico new file mode 100644 index 0000000000000000000000000000000000000000..68aa3719fb523eccd4c4a706e4198ca1be2b4c62 GIT binary patch literal 766 zcmb_ayGjE=6ul!BJ4Il&5f%%#i;YeE0sqBX?6q(TQ7j^}Bh9<%xts4i6 zkcy&!=Yp>fdCw6P!YMX?g~S3@L(=jS0+)s|NiKlEgL>VOVf)WTfR)85V$RN>JwSV-vWY^X3AQl6o~-A`A21P`H#(L`ua zC6p2|SPTx|B;lEdR<4J97z(@|!YJx7#d!1r3hTe|MU4YoP< Ob-aH+fF44>&V2wPTAUpK literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/visupng/VisualPng.png b/extern/libpng/include/contrib/visupng/VisualPng.png new file mode 100644 index 0000000000000000000000000000000000000000..c6aa80a9bfa275137e429498bc785cb2dbcdb382 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;SkfJR9T^xl_H+M9WCils0(?ST zf%J9`j>RRx2|yNONswPKgTu2MX+Tbfr;B5V#O34!2UcDl9v_~y3Xga?K0NvO|~WI+Z?ismL3#z>)ClO+n69&&Pt@)((moHOva6OfZ2FlX_Z0}8s!jvZ1^ zUz2uRL2<>QLkbEXTG%~o9y17?WOH!($Y?g1Vbg3Ozf`fCd_X%HJYD@<);T3K0RUGo BL5BbU literal 0 HcmV?d00001 diff --git a/extern/libpng/include/contrib/visupng/VisualPng.rc b/extern/libpng/include/contrib/visupng/VisualPng.rc new file mode 100644 index 0000000000..6e0623a73c --- /dev/null +++ b/extern/libpng/include/contrib/visupng/VisualPng.rc @@ -0,0 +1,152 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +VISUALPNG MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Open Image...\tCtrl+O", IDM_FILE_OPEN + MENUITEM "Save &As...", IDM_FILE_SAVE + MENUITEM SEPARATOR + MENUITEM "&Next Image\tCtrl+N", IDM_FILE_NEXT + MENUITEM "Pre&vious Image\tCtrl+V", IDM_FILE_PREVIOUS + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+X", IDM_FILE_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&Stretch", IDM_OPTIONS_STRETCH, CHECKED + END + POPUP "&Help" + BEGIN + MENUITEM "&About", IDM_HELP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +VISUALPNG ACCELERATORS DISCARDABLE +BEGIN + "N", IDM_FILE_NEXT, VIRTKEY, CONTROL, NOINVERT + "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT + "P", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT + "V", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT + "X", IDM_FILE_EXIT, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +VISUALPNG ICON DISCARDABLE "VisualPng.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUTBOX DIALOG DISCARDABLE 0, 0, 186, 94 +STYLE DS_MODALFRAME | WS_POPUP +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,68,67,50,14 + CTEXT "VisualPng 1.0 - June 2000",IDC_STATIC,49,14,88,8 + LTEXT "a PNG image viewer",IDC_STATIC,60,30,66,8 + LTEXT "(c) Willem van Schaik, 2000",IDC_STATIC,48,52,90,8 + LTEXT "to demonstrate the use of libpng in Visual C", + IDC_STATIC,25,38,136,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "ABOUTBOX", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/extern/libpng/include/contrib/visupng/cexcept.h b/extern/libpng/include/contrib/visupng/cexcept.h new file mode 100644 index 0000000000..5f45d76975 --- /dev/null +++ b/extern/libpng/include/contrib/visupng/cexcept.h @@ -0,0 +1,248 @@ +/*=== +cexcept.h 2.0.1 (2008-Jul-19-Sat) +http://www.nicemice.net/cexcept/ +Adam M. Costello +http://www.nicemice.net/amc/ + +An interface for exception-handling in ANSI C (C89 and subsequent ISO +standards), developed jointly with Cosmin Truta. + + Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta. + This software may be modified only if its author and version + information is updated accurately, and may be redistributed + only if accompanied by this unaltered notice. Subject to those + restrictions, permission is granted to anyone to do anything + with this software. The copyright holders make no guarantees + regarding this software, and are not responsible for any damage + resulting from its use. + +The cexcept interface is not compatible with and cannot interact +with system exceptions (like division by zero or memory segmentation +violation), compiler-generated exceptions (like C++ exceptions), or +other exception-handling interfaces. + +When using this interface across multiple .c files, do not include +this header file directly. Instead, create a wrapper header file that +includes this header file and then invokes the define_exception_type +macro (see below). The .c files should then include that header file. + +The interface consists of one type, one well-known name, and six macros. + + +define_exception_type(type_name); + + This macro is used like an external declaration. It specifies + the type of object that gets copied from the exception thrower to + the exception catcher. The type_name can be any type that can be + assigned to, that is, a non-constant arithmetic type, struct, union, + or pointer. Examples: + + define_exception_type(int); + + enum exception { out_of_memory, bad_arguments, disk_full }; + define_exception_type(enum exception); + + struct exception { int code; const char *msg; }; + define_exception_type(struct exception); + + Because throwing an exception causes the object to be copied (not + just once, but twice), programmers may wish to consider size when + choosing the exception type. + + +struct exception_context; + + This type may be used after the define_exception_type() macro has + been invoked. A struct exception_context must be known to both + the thrower and the catcher. It is expected that there be one + context for each thread that uses exceptions. It would certainly + be dangerous for multiple threads to access the same context. + One thread can use multiple contexts, but that is likely to be + confusing and not typically useful. The application can allocate + this structure in any way it pleases--automatic, static, or dynamic. + The application programmer should pretend not to know the structure + members, which are subject to change. + + +struct exception_context *the_exception_context; + + The Try/Catch and Throw statements (described below) implicitly + refer to a context, using the name the_exception_context. It is + the application's responsibility to make sure that this name yields + the address of a mutable (non-constant) struct exception_context + wherever those statements are used. Subject to that constraint, the + application may declare a variable of this name anywhere it likes + (inside a function, in a parameter list, or externally), and may + use whatever storage class specifiers (static, extern, etc) or type + qualifiers (const, volatile, etc) it likes. Examples: + + static struct exception_context + * const the_exception_context = &foo; + + { struct exception_context *the_exception_context = bar; ... } + + int blah(struct exception_context *the_exception_context, ...); + + extern struct exception_context the_exception_context[1]; + + The last example illustrates a trick that avoids creating a pointer + object separate from the structure object. + + The name could even be a macro, for example: + + struct exception_context ec_array[numthreads]; + #define the_exception_context (ec_array + thread_id) + + Be aware that the_exception_context is used several times by the + Try/Catch/Throw macros, so it shouldn't be expensive or have side + effects. The expansion must be a drop-in replacement for an + identifier, so it's safest to put parentheses around it. + + +void init_exception_context(struct exception_context *ec); + + For context structures allocated statically (by an external + definition or using the "static" keyword), the implicit + initialization to all zeros is sufficient, but contexts allocated + by other means must be initialized using this macro before they + are used by a Try/Catch statement. It does no harm to initialize + a context more than once (by using this macro on a statically + allocated context, or using this macro twice on the same context), + but a context must not be re-initialized after it has been used by a + Try/Catch statement. + + +Try statement +Catch (expression) statement + + The Try/Catch/Throw macros are capitalized in order to avoid + confusion with the C++ keywords, which have subtly different + semantics. + + A Try/Catch statement has a syntax similar to an if/else statement, + except that the parenthesized expression goes after the second + keyword rather than the first. As with if/else, there are two + clauses, each of which may be a simple statement ending with a + semicolon or a brace-enclosed compound statement. But whereas + the else clause is optional, the Catch clause is required. The + expression must be a modifiable lvalue (something capable of being + assigned to) of the same type (disregarding type qualifiers) that + was passed to define_exception_type(). + + If a Throw that uses the same exception context as the Try/Catch is + executed within the Try clause (typically within a function called + by the Try clause), and the exception is not caught by a nested + Try/Catch statement, then a copy of the exception will be assigned + to the expression, and control will jump to the Catch clause. If no + such Throw is executed, then the assignment is not performed, and + the Catch clause is not executed. + + The expression is not evaluated unless and until the exception is + caught, which is significant if it has side effects, for example: + + Try foo(); + Catch (p[++i].e) { ... } + + IMPORTANT: Jumping into or out of a Try clause (for example via + return, break, continue, goto, longjmp) is forbidden--the compiler + will not complain, but bad things will happen at run-time. Jumping + into or out of a Catch clause is okay, and so is jumping around + inside a Try clause. In many cases where one is tempted to return + from a Try clause, it will suffice to use Throw, and then return + from the Catch clause. Another option is to set a flag variable and + use goto to jump to the end of the Try clause, then check the flag + after the Try/Catch statement. + + IMPORTANT: The values of any non-volatile automatic variables + changed within the Try clause are undefined after an exception is + caught. Therefore, variables modified inside the Try block whose + values are needed later outside the Try block must either use static + storage or be declared with the "volatile" type qualifier. + + +Throw expression; + + A Throw statement is very much like a return statement, except that + the expression is required. Whereas return jumps back to the place + where the current function was called, Throw jumps back to the Catch + clause of the innermost enclosing Try clause. The expression must + be compatible with the type passed to define_exception_type(). The + exception must be caught, otherwise the program may crash. + + Slight limitation: If the expression is a comma-expression, it must + be enclosed in parentheses. + + +Try statement +Catch_anonymous statement + + When the value of the exception is not needed, a Try/Catch statement + can use Catch_anonymous instead of Catch (expression). + + +Everything below this point is for the benefit of the compiler. The +application programmer should pretend not to know any of it, because it +is subject to change. + +===*/ + + +#ifndef CEXCEPT_H +#define CEXCEPT_H + + +#include + +#define define_exception_type(etype) \ +struct exception_context { \ + jmp_buf *penv; \ + int caught; \ + volatile struct { etype etmp; } v; \ +} + +/* etmp must be volatile because the application might use automatic */ +/* storage for the_exception_context, and etmp is modified between */ +/* the calls to setjmp() and longjmp(). A wrapper struct is used to */ +/* avoid warnings about a duplicate volatile qualifier in case etype */ +/* already includes it. */ + +#define init_exception_context(ec) ((void)((ec)->penv = 0)) + +#define Try \ + { \ + jmp_buf *exception__prev, exception__env; \ + exception__prev = the_exception_context->penv; \ + the_exception_context->penv = &exception__env; \ + if (setjmp(exception__env) == 0) { \ + do + +#define exception__catch(action) \ + while (the_exception_context->caught = 0, \ + the_exception_context->caught); \ + } \ + else { \ + the_exception_context->caught = 1; \ + } \ + the_exception_context->penv = exception__prev; \ + } \ + if (!the_exception_context->caught || action) { } \ + else + +#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0)) +#define Catch_anonymous exception__catch(0) + +/* Try ends with do, and Catch begins with while(0) and ends with */ +/* else, to ensure that Try/Catch syntax is similar to if/else */ +/* syntax. */ +/* */ +/* The 0 in while(0) is expressed as x=0,x in order to appease */ +/* compilers that warn about constant expressions inside while(). */ +/* Most compilers should still recognize that the condition is always */ +/* false and avoid generating code for it. */ + +#define Throw \ + for (;; longjmp(*the_exception_context->penv, 1)) \ + the_exception_context->v.etmp = + + +#endif /* CEXCEPT_H */ diff --git a/extern/libpng/include/contrib/visupng/resource.h b/extern/libpng/include/contrib/visupng/resource.h new file mode 100644 index 0000000000..611dd035f0 --- /dev/null +++ b/extern/libpng/include/contrib/visupng/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by VisualPng.rc +// +#define IDM_FILE_OPEN 40001 +#define IDM_FILE_SAVE 40002 +#define IDM_FILE_NEXT 40003 +#define IDM_FILE_PREVIOUS 40004 +#define IDM_FILE_EXIT 40005 +#define IDM_OPTIONS_BACKGROUND 40006 +#define IDM_OPTIONS_STRETCH 40007 +#define IDM_HELP_ABOUT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/extern/libpng/include/depcomp b/extern/libpng/include/depcomp new file mode 100755 index 0000000000..df8eea7e4c --- /dev/null +++ b/extern/libpng/include/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/extern/libpng/include/example.c b/extern/libpng/include/example.c new file mode 100644 index 0000000000..782c555b7a --- /dev/null +++ b/extern/libpng/include/example.c @@ -0,0 +1,843 @@ + +#if 0 /* in case someone actually tries to compile this */ + +/* example.c - an example of using libpng + * Last changed in libpng 1.5.2 [March 31, 2011] + * This file has been placed in the public domain by the authors. + * Maintained 1998-2011 Glenn Randers-Pehrson + * Maintained 1996, 1997 Andreas Dilger) + * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng-manual.txt is much more verbose then this. If you have not + * read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, is hereby placed + * in the public domain, and therefore does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution; + * see also the programs in the contrib directory. + */ + +#include "png.h" + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!). + */ + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) +#endif + +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp() or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ +#define PNG_BYTES_TO_CHECK 4 +int check_if_png(char *file_name, FILE **fp) +{ + char buf[PNG_BYTES_TO_CHECK]; + + /* Open the prospective PNG file. */ + if ((*fp = fopen(file_name, "rb")) == NULL) + return 0; + + /* Read in some of the signature bytes */ + if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) + return 0; + + /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. + Return nonzero (true) if they match */ + + return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); +} + +/* Read a PNG file. You may want to return an error code if the read + * fails (depending upon the failure). There are two "prototypes" given + * here - one where we are given the filename, and we need to open the + * file, and the other where we are given an open file (possibly with + * some or all of the magic bytes read - see comments above). + */ +#ifdef open_file /* prototype 1 */ +void read_png(char *file_name) /* We need to open the file */ +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + FILE *fp; + + if ((fp = fopen(file_name, "rb")) == NULL) + return (ERROR); + +#else no_open_file /* prototype 2 */ +void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ +{ + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; +#endif no_open_file /* Only use one prototype! */ + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return (ERROR); + } + + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + + if (setjmp(png_jmpbuf(png_ptr))) + { + /* Free all of the memory associated with the png_ptr and info_ptr */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + /* If we get here, we had a problem reading the file */ + return (ERROR); + } + + /* One of the following I/O initialization methods is REQUIRED */ +#ifdef streams /* PNG file I/O method 1 */ + /* Set up the input control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* PNG file I/O method 2 */ + /* If you are using replacement read functions, instead of calling + * png_init_io() here you would call: + */ + png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Use only one I/O method! */ + + /* If we have already read some of the signature */ + png_set_sig_bytes(png_ptr, sig_read); + +#ifdef hilevel + /* + * If you have enough memory to read in the entire image at once, + * and you need to specify only transforms that can be controlled + * with one of the PNG_TRANSFORM_* bits (this presently excludes + * quantizing, filling, setting background, and doing gamma + * adjustment), then you can read the entire image (including + * pixels) into the info structure with this call: + */ + png_read_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* OK, you're doing it the hard way, with the lower-level functions */ + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). REQUIRED + */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); + + /* Set up the data transformations you want. Note that these are all + * optional. Only call them if you want/need them. Many of the + * transformations only work on specific types of images, and many + * are mutually exclusive. + */ + + /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ + png_set_strip_16(png_ptr); + + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + png_set_strip_alpha(png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + png_set_packing(png_ptr); + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). */ + png_set_packswap(png_ptr); + + /* Expand paletted colors into true RGB triplets */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* Expand paletted or RGB images with transparency to full alpha channels + * so the data will be available as RGBA quartets. + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + /* Set the background color to draw transparent and alpha images over. + * It is possible to set the red, green, and blue components directly + * for paletted images instead of supplying a palette index. Note that + * even if the PNG file supplies a background, you are not required to + * use it - you should use the (solid) application background if it has one. + */ + + png_color_16 my_background, *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); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + /* Some suggestions as to how to get a screen gamma value + * + * Note that screen gamma is the display_exponent, which includes + * the CRT_exponent and any correction for viewing conditions + */ + if (/* We have a user-defined screen gamma value */) + { + screen_gamma = user-defined screen_gamma; + } + /* This is one way that applications share the same screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) + { + screen_gamma = atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly + lit room */ + screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ + } + + /* Tell libpng to handle the gamma conversion for you. The final call + * is a good guess for PC generated images, but it should be configurable + * by the user at run time by the user. It is strongly suggested that + * your application support gamma correction. + */ + + int intent; + + if (png_get_sRGB(png_ptr, info_ptr, &intent)) + png_set_gamma(png_ptr, screen_gamma, 0.45455); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + /* Quantize RGB files down to 8 bit palette or reduce palettes + * to the number of colors available on your screen. + */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + int num_palette; + png_colorp palette; + + /* This reduces the image to the application supplied palette */ + if (/* We have our own palette */) + { + /* An array of colors to which the image should be quantized */ + png_color std_color_cube[MAX_SCREEN_COLORS]; + + png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, + MAX_SCREEN_COLORS, NULL, 0); + } + /* This reduces the image to the palette supplied in the file */ + else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, &histogram); + + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 0); + } + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + + /* Invert monochrome files to have 0 as white and 1 as black */ + png_set_invert_mono(png_ptr); + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit_p; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); + png_set_shift(png_ptr, sig_bit_p); + } + + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (color_type & PNG_COLOR_MASK_COLOR) + png_set_bgr(png_ptr); + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + png_set_swap_alpha(png_ptr); + + /* Swap bytes of 16 bit files to least significant byte first */ + png_set_swap(png_ptr); + + /* Add filler (or alpha) byte (before/after each RGB triplet) */ + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + /* Turn on interlace handling. REQUIRED if you are not using + * png_read_image(). To see how to handle interlacing passes, + * see the png_read_row() method below: + */ + number_passes = 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 (ie you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* Allocate the memory to hold the image using the fields of info_ptr. */ + + /* The easiest way to read the image: */ + png_bytep row_pointers[height]; + + /* Clear the pointer array */ + for (row = 0; row < height; row++) + row_pointers[row] = NULL; + + for (row = 0; row < height; row++) + row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* Now it's time to read the image. One of these methods is REQUIRED */ +#ifdef entire /* Read the entire image in one go */ + png_read_image(png_ptr, row_pointers); + +#else no_entire /* Read the image one or more scanlines at a time */ + /* The other way to read images - deal with interlacing: */ + + for (pass = 0; pass < number_passes; pass++) + { +#ifdef single /* Read the image a single row at a time */ + for (y = 0; y < height; y++) + { + png_read_rows(png_ptr, &row_pointers[y], NULL, 1); + } + +#else no_single /* Read the image several rows at a time */ + for (y = 0; y < height; y += number_of_rows) + { +#ifdef sparkle /* Read the image using the "sparkle" effect. */ + png_read_rows(png_ptr, &row_pointers[y], NULL, + number_of_rows); +#else no_sparkle /* Read the image using the "rectangle" effect */ + png_read_rows(png_ptr, NULL, &row_pointers[y], + number_of_rows); +#endif no_sparkle /* Use only one of these two methods */ + } + + /* If you want to display the image after every pass, do so here */ +#endif no_single /* Use only one of these two methods */ + } +#endif no_entire /* Use only one of these two methods */ + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); +#endif hilevel + + /* At this point you have read the entire image */ + + /* Clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +/* Progressively read a file */ + +int +initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) +{ + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible in case we are using dynamically + * linked libraries. + */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (*png_ptr == NULL) + { + *info_ptr = NULL; + return (ERROR); + } + + *info_ptr = png_create_info_struct(png_ptr); + + if (*info_ptr == NULL) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf((*png_ptr)))) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new. You will need to provide all three + * function callbacks, even if you aren't using them all. + * If you aren't using all functions, you can specify NULL + * parameters. Even when all three functions are NULL, + * you need to call png_set_progressive_read_fn(). + * These functions shouldn't be dependent on global or + * static variables if you are decoding several images + * simultaneously. You should store stream specific data + * in a separate struct, given as the second parameter, + * and retrieve the pointer from inside the callbacks using + * the function png_get_progressive_ptr(png_ptr). + */ + png_set_progressive_read_fn(*png_ptr, (void *)stream_data, + info_callback, row_callback, end_callback); + + return (OK); +} + +int +process_data(png_structp *png_ptr, png_infop *info_ptr, + png_bytep buffer, png_uint_32 length) +{ + if (setjmp(png_jmpbuf((*png_ptr)))) + { + /* Free the png_ptr and info_ptr memory on error */ + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new also. Simply give it chunks of data as + * they arrive from the data stream (in order, of course). + * On segmented machines, don't give it any more than 64K. + * The library seems to run fine with sizes of 4K, although + * you can give it much less if necessary (I assume you can + * give it chunks of 1 byte, but I haven't tried with less + * than 256 bytes yet). When this function returns, you may + * want to display any rows that were generated in the row + * callback, if you aren't already displaying them there. + */ + png_process_data(*png_ptr, *info_ptr, buffer, length); + return (OK); +} + +info_callback(png_structp png_ptr, png_infop info) +{ + /* Do any setup here, including setting any of the transformations + * mentioned in the Reading PNG files section. For now, you _must_ + * call either png_start_read_image() or png_read_update_info() + * after all the transformations are set (even if you don't set + * any). You may start getting rows before png_process_data() + * returns, so this is your last chance to prepare for that. + */ +} + +row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) +{ + /* + * This function is called for every row in the image. If the + * image is interlaced, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * + * In this function you will receive a pointer to new row data from + * libpng called new_row that is to replace a corresponding row (of + * the same data format) in a buffer allocated by your application. + * + * The new row data pointer "new_row" may be NULL, indicating there is + * no new data to be replaced (in cases of interlace loading). + * + * If new_row is not NULL then you need to call + * png_progressive_combine_row() to replace the corresponding row as + * shown below: + */ + + /* Get pointer to corresponding row in our + * PNG read buffer. + */ + png_bytep old_row = ((png_bytep *)our_data)[row_num]; + + /* If both rows are allocated then copy the new row + * data to the corresponding row data. + */ + if ((old_row != NULL) && (new_row != NULL)) + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* + * The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the new row and the + * old row, as demonstrated above. You can call this function for + * NULL rows (it will just return) and for non-interlaced images + * (it just does the png_memcpy for you) if it will make the code + * easier. Thus, you can just do this for all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row as new_row, and the function will combine + * the old row and the new row. + */ +} + +end_callback(png_structp png_ptr, png_infop info) +{ + /* This function is called when the whole image has been read, + * including any chunks after the image (up to and including + * the IEND). You will usually have the same info chunk as you + * had in the header, although some data may have been added + * to the comments and time fields. + * + * Most people won't do much here, perhaps setting a flag that + * marks the image as finished. + */ +} + +/* Write a png file */ +void write_png(char *file_name /* , ... other image information ... */) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_colorp palette; + + /* Open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return (ERROR); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + return (ERROR); + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return (ERROR); + } + + /* One of the following I/O initialization functions is REQUIRED */ + +#ifdef streams /* I/O initialization method 1 */ + /* Set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* I/O initialization method 2 */ + /* If you are using replacement write functions, instead of calling + * png_init_io() here you would call + */ + png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Only use one initialization method */ + +#ifdef hilevel + /* This is the easy way. Use it if you already have all the + * image info living in the structure. You could "|" many + * PNG_TRANSFORM flags into the png_transforms integer here. + */ + png_write_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* This is the hard way */ + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, + PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Set the palette if there is one. REQUIRED for indexed-color images */ + palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH + * png_sizeof(png_color)); + /* ... Set palette colors ... */ + png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); + /* You must not free palette here, because png_set_PLTE only makes a link to + * the palette that you malloced. Wait until you are about to destroy + * the png structure. + */ + + /* Optional significant bit (sBIT) chunk */ + png_color_8 sig_bit; + + /* If we are dealing with a grayscale image then */ + sig_bit.gray = true_bit_depth; + + /* Otherwise, if we are dealing with a color image then */ + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + + /* If the image has an alpha channel then */ + sig_bit.alpha = true_alpha_bit_depth; + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + png_set_gAMA(png_ptr, info_ptr, gamma); + + /* Optionally write comments into the image */ + text_ptr[0].key = "Title"; + text_ptr[0].text = "Mona Lisa"; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[0].itxt_length = 0; + text_ptr[0].lang = NULL; + text_ptr[0].lang_key = NULL; + text_ptr[1].key = "Author"; + text_ptr[1].text = "Leonardo DaVinci"; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].itxt_length = 0; + text_ptr[1].lang = NULL; + text_ptr[1].lang_key = NULL; + text_ptr[2].key = "Description"; + text_ptr[2].text = ""; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr[2].itxt_length = 0; + text_ptr[2].lang = NULL; + text_ptr[2].lang_key = NULL; + png_set_text(png_ptr, info_ptr, text_ptr, 3); + + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ + + /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored + * on read and, if your application chooses to write them, they must + * be written in accordance with the sRGB profile + */ + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* If you want, you can write the info in two steps, in case you need to + * write your private chunk ahead of PLTE: + * + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + * write_my_chunk(); + * png_write_info(png_ptr, info_ptr); + * + * However, given the level of known- and unknown-chunk support in 1.2.0 + * and up, this should no longer be necessary. + */ + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* Invert monochrome pixels */ + png_set_invert_mono(png_ptr); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* Pack pixels into bytes */ + png_set_packing(png_ptr); + + /* Swap location of alpha bytes from ARGB to RGBA */ + png_set_swap_alpha(png_ptr); + + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + + /* Flip BGR pixels to RGB */ + png_set_bgr(png_ptr); + + /* Swap bytes of 16-bit files to most significant byte first */ + png_set_swap(png_ptr); + + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + png_set_packswap(png_ptr); + + /* Turn on interlace handling if you are not using png_write_image() */ + if (interlacing) + number_passes = png_set_interlace_handling(png_ptr); + + else + number_passes = 1; + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + png_uint_32 k, height, width; + png_byte image[height][width*bytes_per_pixel]; + png_bytep row_pointers[height]; + + if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error (png_ptr, "Image is too tall to process in memory"); + + for (k = 0; k < height; k++) + row_pointers[k] = image + k*width*bytes_per_pixel; + + /* One of the following output methods is REQUIRED */ + +#ifdef entire /* Write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* The other way to write the image - deal with interlacing */ + +#else no_entire /* Write out the image data by one or more scanlines */ + + /* The number of passes is either 1 for non-interlaced images, + * or 7 for interlaced images. + */ + for (pass = 0; pass < number_passes; pass++) + { + /* Write a few rows at a time. */ + png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); + + /* If you are only writing one row at a time, this works */ + for (y = 0; y < height; y++) + png_write_rows(png_ptr, &row_pointers[y], 1); + } +#endif no_entire /* Use only one output method */ + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. Shouldn't be necessary in 1.2.0 and up as all the public + * chunks are supported and you can use png_set_unknown_chunks() to + * register unknown chunks into the info structure to be written out. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); +#endif hilevel + + /* If you png_malloced a palette, free it here (don't free info_ptr->palette, + * as recommended in versions 1.0.5m and earlier of this example; if + * libpng mallocs info_ptr->palette, libpng will free it). If you + * allocated it with malloc() instead of png_malloc(), use free() instead + * of png_free(). + */ + png_free(png_ptr, palette); + palette = NULL; + + /* Similarly, if you png_malloced any data that you passed in with + * png_set_something(), such as a hist or trans array, free it here, + * when you can be sure that libpng is through with it. + */ + png_free(png_ptr, trans); + trans = NULL; + /* Whenever you use png_free() it is a good idea to set the pointer to + * NULL in case your application inadvertently tries to png_free() it + * again. When png_free() sees a NULL it returns without action, thus + * avoiding the double-free security problem. + */ + + /* Clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +#endif /* if 0 */ diff --git a/extern/libpng/include/libpng-manual.txt b/extern/libpng/include/libpng-manual.txt new file mode 100644 index 0000000000..4693408460 --- /dev/null +++ b/extern/libpng/include/libpng-manual.txt @@ -0,0 +1,4214 @@ +libpng-manual.txt - A description on how to use and modify libpng + + libpng version 1.5.2 - March 31, 2011 + Updated and distributed by Glenn Randers-Pehrson + + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.5.2 - March 31, 2011 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) break this rule, but it's almost always safe +to assume that a (png_struct*) has to be passed to call an API function. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments, +however internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have an matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with _fixed appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add -DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +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. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +scripts/pnglibconf.mak contains a set of make rules for doing the same thing if +configure is not used, and many of the makefiles in the scripts directory use +this approach. + +When rebuilding simply write new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. pngusr.dfa should contain lines of the +following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +C. Configuration using PNG_USR_CONFIG + +If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file +pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. pngusr.h should contain only macro +definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + 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, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +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 +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +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(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is 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. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_structp png_ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_structp png_ptr, + png_uint_32 row, int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +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 +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +User limits + +The PNG specification allows the width and height of an image to be as +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 + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +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(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +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_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + + palette - the palette for the file + (array of png_color) + + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + file_srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + + num_comments - number of comments + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + + text_ptr[i].text - text comments for current + keyword. Can be empty. + + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + + text_ptr[i].lang - language of comment (empty + string for unknown). + + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + + offset_x - positive offset from the left edge + of the screen + + offset_y - positive offset from the top edge + of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + + res_x - pixels/unit physical resolution in + x direction + + res_y - pixels/unit physical resolution in + x direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + + unknowns[i].name - name of unknown chunk + + unknowns[i].data - data of unknown chunk + + unknowns[i].size - size of unknown chunk's data + + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 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. + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see the png_info definition in png.h and 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.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +Input transformations + +After you've read the header information, you can set up the library +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. + +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). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +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 +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(). + +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 +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +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 (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + + 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. + +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.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_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); + +See below for png_set_background(), which does the correct composition on a +single opaque color. This is probably what you should do in all cases rather +than use png_set_strip_alpha() - unless you know for sure that it is the wrong +thing to do. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are convertion of grayscale to indexed images (which can be +done trivially in the application) and convertion 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 + TO + 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() (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() or + png_set_rgb_to_Y(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "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 +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +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); + + error_action = 1: silently do the conversion + + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +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 +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: + + 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, +Copyright (c) 1998-01-04 Charles Poynton + + 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_gray_1_2_4_to_8(), +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). + + 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); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +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); + } + + /* 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 */ + + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +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. + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_gamma); + + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + 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, +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): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + 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 +after all of the other transformations have been processed. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +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 +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Remember: Before you call png_read_update_info(), the png_get_ +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() (unless you call +png_read_update_info()) or call this function multiple times, or any +of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7); +a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If, as is likely, you want libpng to expand the images, call this before +calling png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. This function can be +called even if the file is not interlaced, where it will return one pass. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself, however you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach) see +how pngvalid.c does it. + +Finishing a sequential read + +After you are finished reading the image through the +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. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + + This is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases if you switch on interlace handling; + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + + if (!fp) + return (ERROR); + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (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); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +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(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_structp png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +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 +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. + */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application wants to start and stop using particular filters during +compression, it should start out with all of the filters (to ensure that +the previous row of pixels will be stored in case it's needed later), +and then add and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +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. + + #include zlib.h + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + + width - holds the width of the image + in pixels (up to 2^31). + + height - holds the height of the image + in pixels (up to 2^31). + + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + png_set_tIME(png_ptr, info_ptr, mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + + offset_x - positive offset from the left + edge of the screen + + offset_y - positive offset from the top + edge of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + + res_x - pixels/unit physical resolution + in x direction + + res_y - pixels/unit physical resolution + in y direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct). + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + + Author Name of image's creator + + Description Description of image (possibly long) + + Copyright Copyright notice + + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + + Software Software used to create the image + + Disclaimer Legal disclaimer + + Warning Warning of nature of content + + Source Device used to create the image + + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +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. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + + else + { + sig_bit.gray = true_bit_depth; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +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): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + 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 +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). + +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. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all the sub-images +(png_set_interlace_handling() returns the number of sub-images.) + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, number_of_rows); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then clears the newly +allocated memory to zero. There is limited support for certain systems +with segmented memory architectures and the types of pointers declared by +png.h match this; you will have to use appropriate pointers in your +application. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +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 + +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 +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h. + +Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +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. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +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); + + png_set_compression_window_bits(png_ptr, + window_bits); + + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if (PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 1.4.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_FILTER_SUB + PNG_ASM_FLAG_MMX_READ_FILTER_UP + PNG_ASM_FLAG_MMX_READ_FILTER_AVG + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +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 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 +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +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 +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 +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +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 +function) incorrectly returned a value of type png_uint_32. + +A. Changes that affect users of libpng + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API, however the ability to directly access +the main libpng control structures, png_struct and png_info, deprecated +in earlier versions of libpng, has been completely removed from +libpng 1.5. + +We no longer include zlib.h in png.h. Applications that need access +to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether it is placed prior to or after +the '"#include png.h"' directive. + +We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), +png_memcmp(), png_sprintf, and png_memcpy() macros into a private +header file (pngpriv.h) that is not accessible to applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare +parts of the API. Some API functions with arguments that are pointers to +data not modified within the function have been corrected to declare +these arguments with PNG_CONST. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +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, 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 +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 +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. + +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 +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +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 +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.) + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +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. + +B. Changes to the build and configuration of libpng + +Details of internal changes to the library code can be found in the CHANGES +file. These will be of no concern to the vast majority of library users or +builders, however the few who configure libpng to a non-default feature +set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed, however library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +B.1 Specific changes to library configuration capabilities + +The library now supports a complete fixed point implementation and can +thus be used on systems which have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far (__cdecl on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and should not, check for the 'NO' macro which will not +normally be defined even if the feature is not supported. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point, however it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +B.2 Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, when the exported header file pnglibconf.h is built. +pngconf.h no longer includes pngusr.h, therefore it is ignored after the +build of pnglibconf.h and it is never included in an application build. + +The rarely used alternative of adding a list of feature macros to the +CFLAGS setting in the build also still works, however the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work, this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off dependent features are +also removed. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and a case where pngusr.h is still required. + +XI. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +XII. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +We also accept patches built from the tar or zip distributions, and +simple verbal discriptions of bug fixes, reported either to the +SourceForge bug tracker or to the png-mng-implement at lists.sf.net +mailing list. + +XIII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programmers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG_". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +XIV. Y2K Compliance in libpng + +March 31, 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.2 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 +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. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +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, +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. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/extern/libpng/include/libpng.3 b/extern/libpng/include/libpng.3 new file mode 100644 index 0000000000..3a7ca6e666 --- /dev/null +++ b/extern/libpng/include/libpng.3 @@ -0,0 +1,5461 @@ +.TH LIBPNG 3 "March 31, 2011" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.2 +.SH SYNOPSIS +\fI\fB + +\fB#include \fP + +\fI\fB + +\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP + +\fI\fB + +\fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_calloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP + +\fI\fB + +\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP + +\fI\fB + +\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask)\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_err (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_default (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_bit_depth (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_bKGD (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_channels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_chunk_cache_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_alloc_size_t png_get_chunk_malloc_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_color_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_compression_buffer_size (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_compression_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_copyright (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_current_row_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_current_pass_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_error_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_filter_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_height (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_width (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_interlace_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_const_bytep png_get_io_chunk_name (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_chunk_type (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_state (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_libpng_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_mem_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_oFFs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_pixel_aspect_ratio (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs_dpi (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_pixel_aspect_ratio_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_progressive_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_PLTE (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_rgb_to_gray_status (png_const_structp \fIpng_ptr) + +\fBpng_uint_32 png_get_rowbytes (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_bytepp png_get_rows (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sBIT (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, double* \fP\fIwidth\fP\fB, double* \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_fixed_pointp \fP\fIwidth\fP\fB, png_fixed_pointp \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_s (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_charpp \fP\fIwidth\fP\fB, png_charpp \fIheight\fP\fB);\fP + +\fI\fB + +\fBpng_bytep png_get_signature (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sPLT (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sRGB (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int \fI*file_srgb_intent\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_text (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tIME (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tRNS (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans_alpha\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_color\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_uint_31 (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_unknown_chunks (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_chunk_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_height_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_transform_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_width_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_valid (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_x_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_x_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_y_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_y_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fI\fB + +\fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fI\fB + +\fBvoid png_longjmp (png_structp \fP\fIpng_ptr\fP\fB, int \fIval\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_default (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_warn (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_permitted\fP\fB);\fP + +\fI\fB + +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP + +\fI\fB + +\fBpng_size_t png_process_data_pause \fP\fI(png_structp\fP\fB, int \fIsave\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_process_data_skip \fI(png_structp\fP\fB);\fP + +\fI\fB + +\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_reset_zstream (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\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 + +\fBvoid png_set_background_fixed (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, png_uint_32 \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_benign_errors (png_structp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_cache_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP + +\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 + +\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_fixed_point_p \fP\fIfilter_weights\fP\fB, png_fixed_point_p \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIscreen_gamma\fP\fB, png_uint_32 \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP + +\fI\fB + +\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP + +\fI\fB + +\fBjmp_buf* png_set_longjmp_fn (png_structp \fP\fIpng_ptr\fP\fB, png_longjmp_ptr \fP\fIlongjmp_fn\fP\fB, size_t \fIjmp_buf_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIuser_chunk_cache_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_buffer_size (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_mem_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_palette_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_quantize (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_quantize\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_uint_32 \fP\fIred\fP\fB, png_uint_32 \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_fixed_point \fP\fIwidth\fP\fB, png_fixed_point \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\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 + +\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_error_numbers (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIstrip_mode\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\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 + +\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans_alpha\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_color\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS_to_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_unknown_chunk_location (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP + +\fI\fB + +\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP + +\fI\fB + +.SH DESCRIPTION +The +.I libpng +library supports encoding, decoding, and various manipulations of +the Portable Network Graphics (PNG) format image files. It uses the +.IR zlib(3) +compression library. +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.2 - March 31, 2011 + Updated and distributed by Glenn Randers-Pehrson + + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.5.2 - March 31, 2011 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +.SH I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +.SH II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) break this rule, but it's almost always safe +to assume that a (png_struct*) has to be passed to call an API function. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +.SS Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments, +however internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have an matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with _fixed appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +.SS Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add -DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +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. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +scripts/pnglibconf.mak contains a set of make rules for doing the same thing if +configure is not used, and many of the makefiles in the scripts directory use +this approach. + +When rebuilding simply write new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. pngusr.dfa should contain lines of the +following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +C. Configuration using PNG_USR_CONFIG + +If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file +pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. pngusr.h should contain only macro +definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +.SH III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +.SS Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + 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, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +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 +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +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(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is 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. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +.SS Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_structp png_ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_structp png_ptr, + png_uint_32 row, int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +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 +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +.SS User limits + +The PNG specification allows the width and height of an image to be as +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 + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +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(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +.SS The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +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_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + + palette - the palette for the file + (array of png_color) + + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + file_srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + + num_comments - number of comments + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + + text_ptr[i].text - text comments for current + keyword. Can be empty. + + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + + text_ptr[i].lang - language of comment (empty + string for unknown). + + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + + offset_x - positive offset from the left edge + of the screen + + offset_y - positive offset from the top edge + of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + + res_x - pixels/unit physical resolution in + x direction + + res_y - pixels/unit physical resolution in + x direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + + unknowns[i].name - name of unknown chunk + + unknowns[i].data - data of unknown chunk + + unknowns[i].size - size of unknown chunk's data + + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 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. + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see the png_info definition in png.h and 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.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +.SS Input transformations + +After you've read the header information, you can set up the library +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. + +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). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +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 +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(). + +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 +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +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 (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + + 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. + +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.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_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); + +See below for png_set_background(), which does the correct composition on a +single opaque color. This is probably what you should do in all cases rather +than use png_set_strip_alpha() - unless you know for sure that it is the wrong +thing to do. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are convertion of grayscale to indexed images (which can be +done trivially in the application) and convertion 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 + TO + 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() (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() or + png_set_rgb_to_Y(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "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 +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +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); + + error_action = 1: silently do the conversion + + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +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 +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: + + 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, +Copyright (c) 1998-01-04 Charles Poynton + + 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_gray_1_2_4_to_8(), +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). + + 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); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +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); + } + + /* 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 */ + + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +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. + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_gamma); + + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + 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, +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): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + 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 +after all of the other transformations have been processed. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +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 +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Remember: Before you call png_read_update_info(), the png_get_ +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +.SS Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() (unless you call +png_read_update_info()) or call this function multiple times, or any +of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7); +a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If, as is likely, you want libpng to expand the images, call this before +calling png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. This function can be +called even if the file is not interlaced, where it will return one pass. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself, however you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach) see +how pngvalid.c does it. + +.SS Finishing a sequential read + +After you are finished reading the image through the +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. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +.SS Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + + This is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases if you switch on interlace handling; + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +.SH IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +.SS Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + + if (!fp) + return (ERROR); + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (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); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +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(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +.SS Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_structp png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +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 +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. + */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application wants to start and stop using particular filters during +compression, it should start out with all of the filters (to ensure that +the previous row of pixels will be stored in case it's needed later), +and then add and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +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. + + #include zlib.h + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +.SS Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + + width - holds the width of the image + in pixels (up to 2^31). + + height - holds the height of the image + in pixels (up to 2^31). + + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + png_set_tIME(png_ptr, info_ptr, mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + + offset_x - positive offset from the left + edge of the screen + + offset_y - positive offset from the top + edge of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + + res_x - pixels/unit physical resolution + in x direction + + res_y - pixels/unit physical resolution + in y direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct). + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + + Author Name of image's creator + + Description Description of image (possibly long) + + Copyright Copyright notice + + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + + Software Software used to create the image + + Disclaimer Legal disclaimer + + Warning Warning of nature of content + + Source Device used to create the image + + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +.SS Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +.SS The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +.SS The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +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. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + + else + { + sig_bit.gray = true_bit_depth; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +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): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + 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 +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). + +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. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +.SS Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all the sub-images +(png_set_interlace_handling() returns the number of sub-images.) + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, number_of_rows); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +.SS Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +.SH V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then clears the newly +allocated memory to zero. There is limited support for certain systems +with segmented memory architectures and the types of pointers declared by +png.h match this; you will have to use appropriate pointers in your +application. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +.SS Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +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 + +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 +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +.SS Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +.SS Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +.SS Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +.SS Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h. + +.SS Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +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. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +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); + + png_set_compression_window_bits(png_ptr, + window_bits); + + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +.SS Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +.SS Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +.SS Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if (PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +.SH VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +.SH VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 1.4.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +.SH VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_FILTER_SUB + PNG_ASM_FLAG_MMX_READ_FILTER_UP + PNG_ASM_FLAG_MMX_READ_FILTER_AVG + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +.SH IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +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 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 +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +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 +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 +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +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 +function) incorrectly returned a value of type png_uint_32. + +A. Changes that affect users of libpng + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API, however the ability to directly access +the main libpng control structures, png_struct and png_info, deprecated +in earlier versions of libpng, has been completely removed from +libpng 1.5. + +We no longer include zlib.h in png.h. Applications that need access +to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether it is placed prior to or after +the '"#include png.h"' directive. + +We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), +png_memcmp(), png_sprintf, and png_memcpy() macros into a private +header file (pngpriv.h) that is not accessible to applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare +parts of the API. Some API functions with arguments that are pointers to +data not modified within the function have been corrected to declare +these arguments with PNG_CONST. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +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, 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 +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 +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. + +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 +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +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 +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.) + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +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. + +B. Changes to the build and configuration of libpng + +Details of internal changes to the library code can be found in the CHANGES +file. These will be of no concern to the vast majority of library users or +builders, however the few who configure libpng to a non-default feature +set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed, however library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +B.1 Specific changes to library configuration capabilities + +The library now supports a complete fixed point implementation and can +thus be used on systems which have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far (__cdecl on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and should not, check for the 'NO' macro which will not +normally be defined even if the feature is not supported. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point, however it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +B.2 Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, when the exported header file pnglibconf.h is built. +pngconf.h no longer includes pngusr.h, therefore it is ignored after the +build of pnglibconf.h and it is never included in an application build. + +The rarely used alternative of adding a list of feature macros to the +CFLAGS setting in the build also still works, however the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work, this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off dependent features are +also removed. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and a case where pngusr.h is still required. + +.SH XI. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +.SH XII. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +We also accept patches built from the tar or zip distributions, and +simple verbal discriptions of bug fixes, reported either to the +SourceForge bug tracker or to the png-mng-implement at lists.sf.net +mailing list. + +.SH XIII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programmers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG_". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +.SH XIV. Y2K Compliance in libpng + +March 31, 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.2 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 +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. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +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, +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. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group + +.SH NOTE + +Note about libpng version numbers: + +Due to various miscommunications, unforeseen code incompatibilities +and occasional factors outside the authors' control, version numbering +on the library has not always been consistent and straightforward. +The following table summarizes matters since version 0.89c, which was +the first widely used release: + + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- + 0.89c ("beta 3") 0.89 89 1.0.89 + 0.90 ("beta 4") 0.90 90 0.90 + 0.95 ("beta 5") 0.95 95 0.95 + 0.96 ("beta 6") 0.96 96 0.96 + 0.97b ("beta 7") 1.00.97 97 1.0.1 + 0.97c 0.97 97 2.0.97 + 0.98 0.98 98 2.0.98 + 0.99 0.99 98 2.0.99 + 0.99a-m 0.99 99 2.0.99 + 1.00 1.00 100 2.1.0 + 1.0.0 1.0.0 100 2.1.0 + 1.0.0 (from here on, the 100 2.1.0 + 1.0.1 png.h string is 10001 2.1.0 + 1.0.1a-e identical to the 10002 from here on, the + 1.0.2 source version) 10002 shared library is 2.V + 1.0.2a-b 10003 where V is the source + 1.0.1 10001 code version except as + 1.0.1a-e 10002 2.1.0.1a-e noted. + 1.0.2 10002 2.1.0.2 + 1.0.2a-b 10003 2.1.0.2a-b + 1.0.3 10003 2.1.0.3 + 1.0.3a-d 10004 2.1.0.3a-d + 1.0.4 10004 2.1.0.4 + 1.0.4a-f 10005 2.1.0.4a-f + 1.0.5 (+ 2 patches) 10005 2.1.0.5 + 1.0.5a-d 10006 2.1.0.5a-d + 1.0.5e-r 10100 2.1.0.5e-r + 1.0.5s-v 10006 2.1.0.5s-v + 1.0.6 (+ 3 patches) 10006 2.1.0.6 + 1.0.6d-g 10007 2.1.0.6d-g + 1.0.6h 10007 10.6h + 1.0.6i 10007 10.6i + 1.0.6j 10007 2.1.0.6j + 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 + 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 + 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 + 1.0.7 1 10007 2.1.0.7 + 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + 1.0.8rc1 1 10008 2.1.0.8rc1 + 1.0.8 1 10008 2.1.0.8 + 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + 1.0.9rc1 1 10009 2.1.0.9rc1 + 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + 1.0.9rc2 1 10009 2.1.0.9rc2 + 1.0.9 1 10009 2.1.0.9 + 1.0.10beta1 1 10010 2.1.0.10beta1 + 1.0.10rc1 1 10010 2.1.0.10rc1 + 1.0.10 1 10010 2.1.0.10 + 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + 1.0.11rc1 1 10011 2.1.0.11rc1 + 1.0.11 1 10011 2.1.0.11 + 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + 1.0.12rc1 2 10012 2.1.0.12rc1 + 1.0.12 2 10012 2.1.0.12 + 1.1.0a-f - 10100 2.1.1.0a-f abandoned + 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + 1.2.0rc1 3 10200 3.1.2.0rc1 + 1.2.0 3 10200 3.1.2.0 + 1.2.1beta-4 3 10201 3.1.2.1beta1-4 + 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + 1.2.1 3 10201 3.1.2.1 + 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + 1.0.13 10 10013 10.so.0.1.0.13 + 1.2.2 12 10202 12.so.0.1.2.2 + 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + 1.2.3 12 10203 12.so.0.1.2.3 + 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + 1.0.14 10 10014 10.so.0.1.0.14 + 1.2.4 13 10204 12.so.0.1.2.4 + 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + 1.0.15rc1 10 10015 10.so.0.1.0.15rc1 + 1.0.15 10 10015 10.so.0.1.0.15 + 1.2.5 13 10205 12.so.0.1.2.5 + 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5 + 1.0.16 10 10016 10.so.0.1.0.16 + 1.2.6 13 10206 12.so.0.1.2.6 + 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + 1.0.17 10 10017 12.so.0.1.0.17 + 1.2.7 13 10207 12.so.0.1.2.7 + 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + 1.0.18 10 10018 12.so.0.1.0.18 + 1.2.8 13 10208 12.so.0.1.2.8 + 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + 1.2.9beta4-11 13 10209 12.so.0.9[.0] + 1.2.9rc1 13 10209 12.so.0.9[.0] + 1.2.9 13 10209 12.so.0.9[.0] + 1.2.10beta1-7 13 10210 12.so.0.10[.0] + 1.2.10rc1-2 13 10210 12.so.0.10[.0] + 1.2.10 13 10210 12.so.0.10[.0] + 1.4.0beta1-6 14 10400 14.so.0.0[.0] + 1.2.11beta1-4 13 10210 12.so.0.11[.0] + 1.4.0beta7-8 14 10400 14.so.0.0[.0] + 1.2.11 13 10211 12.so.0.11[.0] + 1.2.12 13 10212 12.so.0.12[.0] + 1.4.0beta9-14 14 10400 14.so.0.0[.0] + 1.2.13 13 10213 12.so.0.13[.0] + 1.4.0beta15-36 14 10400 14.so.0.0[.0] + 1.4.0beta37-87 14 10400 14.so.14.0[.0] + 1.4.0rc01 14 10400 14.so.14.0[.0] + 1.4.0beta88-109 14 10400 14.so.14.0[.0] + 1.4.0rc02-08 14 10400 14.so.14.0[.0] + 1.4.0 14 10400 14.so.14.0[.0] + 1.4.1beta01-03 14 10401 14.so.14.1[.0] + 1.4.1rc01 14 10401 14.so.14.1[.0] + 1.4.1beta04-12 14 10401 14.so.14.1[.0] + 1.4.1 14 10401 14.so.14.1[.0] + 1.4.2 14 10402 14.so.14.2[.0] + 1.4.3 14 10403 14.so.14.3[.0] + 1.4.4 14 10404 14.so.14.4[.0] + 1.5.0beta01-58 15 10500 15.so.15.0[.0] + 1.5.0rc01-07 15 10500 15.so.15.0[.0] + 1.5.0 15 10500 15.so.15.0[.0] + 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] + +Henceforth the source version will match the shared-library minor +and patch numbers; the shared-library major version number will be +used for changes in backward compatibility, as it is intended. The +PNG_PNGLIB_VER macro, which is not used within libpng but is available +for applications, is an unsigned integer of the form xyyzz corresponding +to the source version x.y.z (leading zeros in y and z). Beta versions +were given the previous public release number plus a letter, until +version 1.0.6j; from then on they were given the upcoming public +release number plus "betaNN" or "rcN". + +.SH "SEE ALSO" +.BR "png"(5), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) + +.LP +.IR libpng : +.IP +http://libpng.sourceforge.net (follow the [DOWNLOAD] link) +http://www.libpng.org/pub/png + +.LP +.IR zlib : +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ftp.info-zip.org/pub/infozip/zlib + +.LP +.IR PNG specification: RFC 2083 +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ds.internic.net/rfc/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html + +.LP +In the case of any inconsistency between the PNG specification +and this library, the specification takes precedence. + +.SH AUTHORS +This man page: Glenn Randers-Pehrson + + +The contributing authors would like to thank all those who helped +with testing, bug fixes, and patience. This wouldn't have been +possible without all of you. + +Thanks to Frank J. T. Wojcik for helping with the documentation. + +Libpng version 1.5.2 - March 31, 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). + +Supported by the PNG development group +.br +png-mng-implement at lists.sf.net +(subscription required; visit +png-mng-implement at lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe). + +.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +(This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail.) + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.2, March 31, 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 + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your + enjoyment of the library or against infringement. + There is no warranty that our efforts or the library + will fulfill any of your particular purposes or needs. + This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and + effort is with the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson +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 + Glenn Randers-Pehrson + Willem van Schaik + +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, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +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, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and + must not be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from + any source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +March 31, 2011 + +.\" end of man page + diff --git a/extern/libpng/include/libpng.pc.in b/extern/libpng/include/libpng.pc.in new file mode 100644 index 0000000000..3e7e2c58a7 --- /dev/null +++ b/extern/libpng/include/libpng.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +Name: libpng +Description: Loads and saves PNG files +Version: @PNGLIB_VERSION@ +Libs: -L${libdir} -lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ +Libs.private: @LIBS@ +Cflags: -I${includedir} diff --git a/extern/libpng/include/libpngpf.3 b/extern/libpng/include/libpngpf.3 new file mode 100644 index 0000000000..cc7f13870a --- /dev/null +++ b/extern/libpng/include/libpngpf.3 @@ -0,0 +1,30 @@ +.TH LIBPNGPF 3 "March 31, 2011" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.2 +(private functions) +.SH SYNOPSIS +\fB#include \fI"pngpriv.h" + +\fI\fB + +\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer \fP\fImaintained\fP\fB, now \fIthat + +\fBthe private function prototypes are hidden in pngpriv.h and not \fIaccessible + +\fBto applications. Look in pngpriv.h for the prototypes and a short \fIdescription + +\fBof each \fIfunction. + +\fI\fB + +.SH DESCRIPTION +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. + +.SH SEE ALSO +.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.SH AUTHOR +Glenn Randers-Pehrson diff --git a/extern/libpng/include/ltmain.sh b/extern/libpng/include/ltmain.sh new file mode 100755 index 0000000000..3061e3c5a2 --- /dev/null +++ b/extern/libpng/include/ltmain.sh @@ -0,0 +1,9636 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3293 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="grep -E"} +: ${FGREP="grep -F"} +: ${GREP="grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/extern/libpng/include/missing b/extern/libpng/include/missing new file mode 100755 index 0000000000..28055d2ae6 --- /dev/null +++ b/extern/libpng/include/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/extern/libpng/include/png.5 b/extern/libpng/include/png.5 new file mode 100644 index 0000000000..f4ccec0a94 --- /dev/null +++ b/extern/libpng/include/png.5 @@ -0,0 +1,74 @@ +.TH PNG 5 "March 31, 2011" +.SH NAME +png \- Portable Network Graphics (PNG) format +.SH DESCRIPTION +PNG (Portable Network Graphics) is an extensible file format for the +lossless, portable, well-compressed storage of raster images. PNG provides +a patent-free replacement for GIF and can also replace many +common uses of TIFF. Indexed-color, grayscale, and truecolor images are +supported, plus an optional alpha channel. Sample depths range from +1 to 16 bits. +.br + +PNG is designed to work well in online viewing applications, such as the +World Wide Web, so it is fully streamable with a progressive display +option. PNG is robust, providing both full file integrity checking and +fast, simple detection of common transmission errors. Also, PNG can store +gamma and chromaticity data for improved color matching on heterogeneous +platforms. + +.SH "SEE ALSO" +.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.LP +PNG specification (second edition), November 2003: +.IP +.br + LX-}`>=f8Y0x?_}m=8Q`%n#hU_5OiaM90Zxtq1>=CgTfsNH zyhE`{nwsjeShHXcFRV>~hi`yq2v*YHBRtd~Fu*+^LY^4lCw1}#Lva_%-vvRO=aKPAMFitLB9!@Se7YxRO;(_xakVqs4H@^T1A;613B7T`LfloCM zC>s>YhTw#8BK~ij^a5~J00TIJnM42(oCyqPI(Y@00RRyA^t=CpnFWBbLcymyB_03- z0x_M|W@3T<`-BN}TAvxt!Yd50@*zZ&*pN77LnCW9lz^y8aNMcnEYqn3{J(Y(W-t^0 zvHZ$XfCC^V5CqH&h5jdw2?Phg5ME(JD6^7?wOdfuSH8H0zP}N;;+36~Ie_ET2?Phj z0ewJu_XPOzrM!FkVBFSWa?9PHSVQF9@l6YED#^WWRML1J9VDQieoKN{=G;@B(Vmqw zMZd`y)ni0|7a{dGH#QBu4Xb>^8Ml-38dtbR*{4J6CiE}A`n<^Swi_b~53dp@Oz5&x zqIb>@R2bY|^Eg5Q^oZrcolUy~e~ev4`E;SpK(~nwOpGHYx7IEN6TgtCZ%ql2@{}O= zB=jD|t!NkbZ`gujXu2t1GZEV?OI;QB^sVbc{HllYU92vX0u%;zs?5Dy7i5b^Vr}Pn zO2G4GXu7^$QmgA^)I4+H4Ve#&F8{pR>+ENwX4HwzetiUp&~J{h-wxp)&2&qMG9ULl z$1sGXW1&H@50#Izy=lZUfjypz`|x(CS!BmIDmt4<-iM+7vJJYh6Ok&Y`9uLDz-dii|{T@&nMOnhYGW-(Yq<%v= zZ{=JMeWTwA?P4UG8a$$%3#A_D7*<`B{srsRec$8y$6ez;HO0+<=@)~a+C#KD$fFie zOF5lh(}n6`?kJ=#rB8?(qO_~`d`n%$zP0)o`DHOCeo?6M-Pn1fN6p1D_{#*0&JIPU zL@9JFTVPL!MG(xN{Pyi$)cs@-UVOt7&mCx*p!Qt+LYRroDYFGACZJ{8Pxa zhc4YRL#jc2?yi*%aQ(San~2E>xW1QR0J9uq>9 zE|N+~DEC)g{=F~&W?nheQJ?`Q<2i%Wz?M||p-DL5&AOs`qIe3z=N#%2ExTl7#Mi~t zZTvmnY2L6RG=bnbgRr9M+u}{jp7ydMJN^)W@t){SwRelgUb%&^y1 zM;W@kz|uUoUabJ?0dbrrlPe>APntXLz&pJ5ZWI7}GEh1`;2^(^ytgu48%@k}`m_4R zx8US1L-x+#p75_R@wMZVM}ykuYvioTTGW)v@utp6&FdCbVm5jv1($E4n`7P(vX8P^ zVZA#7-KlKgbTX}&!a_R%ta^0&^b~I$WKg~SIROeW8CO-de{#3jS6!TXFi85;P@Hrz zD3>)2F0f1;VrK&%21hW;jd0Cjw4?npnIr&aVCT_ zW9a^Bg^fd&pImbNpxTP+{rooTc`NU48`F^mV8?f=97sYHnM7{LO)G6#omwpLj@zjk z*`m5o3~<=GP;|qAvDunf<-pg& zIH~t>Us-XJV%rkrKOD99=3flubRj$V{UNE2PCJI@Qi7&wDXM|x@Dll=Tj)D@Y(u1P z7_yCfQ%}|zKKprCcz*XtvG}TKViW44NE~ZF&3pW4f2!sm`cI`U`Bl!2_PqS3Dvok5 z=2eTiaWh#`Q&nhOeYk8Y2gu}DUKS%W-&K5bD>U`DQo92*Z9Jvl-A7zo%D^O5+z3*TS2sjBs^v)SGJg_-$$y+3;FN@u#o{#rqd z=-;Zemc);1)~-n;ZNYgD*QCx)qTS?(6>`Yxu0|T02j9{jA-iY!XBs6VtKgN(?M>3M zXitp$#9|Y^aqefnpO5s_bc&VI`Mol8lb36szrH?8J9^Y{Sh=Zut;vy9EAFY*!eBw< zUh1>Fup<1+##XO=O2huD7w?@yH~akK6(i-EANrw@1tl$;?SdE;AJIJyTU&yrti_SX zqL2K}JyH4R*vHyPyly4H@@Qky6>b`Z!-~dp<=^<0ql8jCIzJ{n2`02PuA?k^A&hB? zljJT{WGG{Bb%mft`m0YCNhgQcH?}Ga`o4KT7r9mpTO|G-ajjf)rUae~l{ z0Rja6`T3xspr4_iba{e!dVHCinSz3e@1>=%j($2G9;~mjBv2nTG{hSR28W4<;$UEa zfq+#nVBJJS0RaHmC@AQFfQX5U(+mu00070t%A%vz78nt@y3y1S5N2m)Kc7E!n|s1o zS3*LZ`|ImCIy_xnT}Vn#B_<}-6cj!`B>eC1D=aTfO-&XS7mt#WfPvpvG$H~507gef za(0FG_V)er^K^NAv$WC-3=ME`ynZ!EiHe1F4i6%tFFzXq(o3jLNqluBO@b zVbTT$78e$QPf^Cm#xylL6B84MYEWEsVPscG4Gj%}gp7rShJJ*J1_uTQ1qZgcwgm+R zTU=lS0|Z`PB(t=$0s#U60RaF30IsgC78d%fuB?oX+;MYqIXXKmDvVH6GZr>DJ8*F|pP|?3h={zu&lnR8iH(zuj*X0tj8%hK4-gJ}V^=2} z6>oEP2?_mre}vT-7)}5HC?_Km6cv1ad;tIecYA?^h0qZY6Aum%b9;T@R8)kCkwQa5 zadmqS2M0SlJZ)}m(EtEcS6dMa3_n3bUt?)wWMf%cS%!(3`QP6|MM@eP`5+-7d3AOF z|Nm+%D{E|VNkkrIXlz47LkkNGKtMq3?d<#K=S5UV_RGudo}K{#0%vG&=I7>ARK#Xx zZ!^wXXe#HK_DO?>Sbn6Qdo$IQAs2u8X6iK7#qpU$!=|P zH#j{eCMlYoeM(75KtVqc5c_+8WeN%km6n;gySbjFueP_g0|EoHwX*;K|7dG)!Bu-G z000IGNklHt z*vcw)0ZfC}7KY%R=*angFf7GDQDX{kit>gDqYzS58b_&yP)Sh~f_vJw^;p^2y#yCM zISs%G832=BMOOfjy#g7m@ zt+jh(w*X#u^vDspeASlpa4&Rno;k@j!sy{`WCR+Uq@`vIjHM+IP*3zXu&|I&vvBhr zt5-6<$;<(2f0#8w1lUp z1?ZrY7`SR}R`W7r#`?tgl6cdPoX?M$DvQtWI;4E?_jQN%)H5pc$G$QI+vc!SEpCkx z#+g9_7fww>9KozuLwWI;j6+9TpAhcZ3t)y?l zdFG(xs{LWrE9KT-raI@mim4p&N{FMfnYvkx$&R<(ms07RfJb`ikXw53l+@$=(}P z?MpK-^c){YFoBt|a4?lG5TfY@J<<>?PQod%2Mgco&28>|0SA}+mYBOllOs`!S5By% zPP)yMN8hY0FHucYC;n_6!ovRAX#_Va6gmb@(5FOo!%@D@y8%T(VK`nksAFI>hf954 z%;R4p&z*B}R#o1+ANee}?qI;Zm|;~&O?-uKytC6Dx4SG1Pcbm+Lj?nKq_BGlH;X_Kt|nbMUG0>1pkOx7k6gb9<~7 zEJCZ>+w;OZRw?IW&lmbl5aqEGH3-e+iMsSUx=|fB7lp(Cl}Z05;e)elg=25lhPU3OFC-`X4O~Pp z(+u8SxX6@Nu-gU$cM%?iDf;}>eg@uPwZ7NbAfwc4%LKv$AESApwMAQTgR)Bj)d}7P zwCAfKkJo5opoC@6Lg<3Mcwvcs4!^5<=}qW6{9VgWp{KyaBpI7crIgaZ7IUp RQSJZ$002ovPDHLkV1iCKFfIT9 literal 0 HcmV?d00001 diff --git a/extern/libpng/include/pnglibconf.h b/extern/libpng/include/pnglibconf.h new file mode 100644 index 0000000000..5f0c8525be --- /dev/null +++ b/extern/libpng/include/pnglibconf.h @@ -0,0 +1,181 @@ + +/* libpng STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.5.0 - last changed on February 11, 2011 */ + +/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* 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_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_USER_WIDTH_MAX 1000000L +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +/* end of settings */ +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGN_MEMORY_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_bKGD_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 +#define PNG_ERROR_TEXT_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_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_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_16_TO_8_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_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_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_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_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_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_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_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_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_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_cHRM_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_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_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_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_zTXt_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/ +/* end of options */ +#endif /* PNGLCONF_H */ diff --git a/extern/libpng/include/projects/visualc71/PRJ0041.mak b/extern/libpng/include/projects/visualc71/PRJ0041.mak new file mode 100644 index 0000000000..e15e12b55f --- /dev/null +++ b/extern/libpng/include/projects/visualc71/PRJ0041.mak @@ -0,0 +1,21 @@ +# Prevent "Cannot find missing dependency..." warnings while compiling +# pngwin.rc (PRJ0041). + +all: $(IntDir)\alloc.h \ + $(IntDir)\fp.h \ + $(IntDir)\m68881.h \ + $(IntDir)\mem.h \ + $(IntDir)\pngusr.h \ + $(IntDir)\strings.h \ + $(IntDir)\unistd.h \ + $(IntDir)\unixio.h + +$(IntDir)\alloc.h \ +$(IntDir)\fp.h \ +$(IntDir)\m68881.h \ +$(IntDir)\mem.h \ +$(IntDir)\pngusr.h \ +$(IntDir)\strings.h \ +$(IntDir)\unistd.h \ +$(IntDir)\unixio.h: + @!echo.>$@ diff --git a/extern/libpng/include/projects/visualc71/README.txt b/extern/libpng/include/projects/visualc71/README.txt new file mode 100644 index 0000000000..625eefcab7 --- /dev/null +++ b/extern/libpng/include/projects/visualc71/README.txt @@ -0,0 +1,58 @@ +Microsoft Developer Studio Project File, Format Version 7.10 for libpng. + +Copyright (C) 2004 Simon-Pierre Cadieux. + +This code is released under the libpng license. +For conditions of distribution and use, see copyright notice in png.h + +NOTE: This project will be removed from libpng-1.5.0. It has +been replaced with the "vstudio" project. + +Assumptions: +* The libpng source files are in ..\.. +* The zlib source files are in ..\..\..\zlib +* The zlib project file is in . /* Warning: This is until the zlib project + files get intergrated into the next zlib release. The final zlib project + directory will then be ..\..\..\zlib\projects\visualc71. */ + +To use: + +1) On the main menu, select "File | Open Solution". + Open "libpng.sln". + +2) Display the Solution Explorer view (Ctrl+Alt+L) + +3) Set one of the project as the StartUp project. If you just want to build the + binaries set "libpng" as the startup project (Select "libpng" tree view + item + Project | Set as StartUp project). If you want to build and test the + binaries set it to "pngtest" (Select "pngtest" tree view item + + Project | Set as StartUp project) + +4) Select "Build | Configuration Manager...". + Choose the configuration you wish to build. + +5) Select "Build | Clean Solution". + +6) Select "Build | Build Solution (Ctrl-Shift-B)" + +This project builds the libpng binaries as follows: + +* Win32_DLL_Release\libpng15.dll DLL build +* Win32_DLL_Debug\libpng15d.dll DLL build (debug version) +* Win32_DLL_VB\libpng15vb.dll DLL build for Visual Basic, using stdcall +* Win32_LIB_Release\libpng.lib static build +* Win32_LIB_Debug\libpngd.lib static build (debug version) + +Notes: + +If you change anything in the source files, or select different compiler +settings, please change the DLL name to something different than any of +the above names. Also, make sure that in your "pngusr.h" you define +PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX according to the +instructions provided in "pngconf.h". + +All DLLs built by this project use the Microsoft dynamic C runtime library +MSVCR71.DLL (MSVCR71D.DLL for debug versions). If you distribute any of the +above mentioned libraries you may have to include this DLL in your package. +For a list of files that are redistributable in Visual Studio see +$(VCINSTALLDIR)\redist.txt. diff --git a/extern/libpng/include/projects/visualc71/README_zlib.txt b/extern/libpng/include/projects/visualc71/README_zlib.txt new file mode 100644 index 0000000000..81d11cbb57 --- /dev/null +++ b/extern/libpng/include/projects/visualc71/README_zlib.txt @@ -0,0 +1,44 @@ +/* WARNING: This file was put in the LibPNG distribution for convenience only. + It is expected to be part of the next zlib release under + "projects\visualc71\README.txt." */ + +Microsoft Developer Studio Project File, Format Version 7.10 for zlib. + +Copyright (C) 2004 Simon-Pierre Cadieux. +Copyright (C) 2004 Cosmin Truta. + +This code is released under the libpng license. +For conditions of distribution and use, see copyright notice in zlib.h. + +NOTE: This project will be removed from libpng-1.5.0. It has +been replaced with the "vstudio" project. + +To use: + +1) On the main menu, select "File | Open Solution". + Open "zlib.sln". + +2) Display the Solution Explorer view (Ctrl+Alt+L) + +3) Set one of the project as the StartUp project. If you just want to build the + binaries set "zlib" as the startup project (Select "zlib" tree view item + + Project | Set as StartUp project). If you want to build and test the + binaries set it to "example" (Select "example" tree view item + Project | + Set as StartUp project), If you want to build the minigzip utility set it to + "minigzip" (Select "minigzip" tree view item + Project | Set as StartUp + project + +4) Select "Build | Configuration Manager...". + Choose the configuration you wish to build. + +5) Select "Build | Clean Solution". + +6) Select "Build | Build Solution (Ctrl-Shift-B)" + +This project builds the zlib binaries as follows: + +* Win32_DLL_Release\zlib1.dll DLL build +* Win32_DLL_Debug\zlib1d.dll DLL build (debug version) +* Win32_LIB_Release\zlib.lib static build +* Win32_LIB_Debug\zlibd.lib static build (debug version) + diff --git a/extern/libpng/include/projects/visualc71/libpng.sln b/extern/libpng/include/projects/visualc71/libpng.sln new file mode 100644 index 0000000000..adce68aae0 --- /dev/null +++ b/extern/libpng/include/projects/visualc71/libpng.sln @@ -0,0 +1,60 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng.vcproj", "{0008960E-E0DD-41A6-8265-00B31DDB4C21}" + ProjectSection(ProjectDependencies) = postProject + {2D4F8105-7D21-454C-9932-B47CAB71A5C0} = {2D4F8105-7D21-454C-9932-B47CAB71A5C0} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngtest", "pngtest.vcproj", "{FD1C2F86-9EEF-47BD-95A4-530917E17FDA}" + ProjectSection(ProjectDependencies) = postProject + {0008960E-E0DD-41A6-8265-00B31DDB4C21} = {0008960E-E0DD-41A6-8265-00B31DDB4C21} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcproj", "{2D4F8105-7D21-454C-9932-B47CAB71A5C0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + DLL Debug = DLL Debug + DLL Release = DLL Release + DLL VB = DLL VB + LIB Debug = LIB Debug + LIB Release = LIB Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Debug.Build.0 = DLL Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Release.ActiveCfg = DLL Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Release.Build.0 = DLL Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL VB.ActiveCfg = DLL VB|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL VB.Build.0 = DLL VB|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Debug.Build.0 = LIB Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Release.ActiveCfg = LIB Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Release.Build.0 = LIB Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Debug.Build.0 = DLL Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Release.ActiveCfg = DLL Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Release.Build.0 = DLL Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL VB.ActiveCfg = DLL VB|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL VB.Build.0 = DLL VB|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Debug.Build.0 = LIB Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Release.ActiveCfg = LIB Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Release.Build.0 = LIB Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Debug.Build.0 = DLL Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Release.ActiveCfg = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Release.Build.0 = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL VB.ActiveCfg = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL VB.Build.0 = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Debug.Build.0 = LIB Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Release.ActiveCfg = LIB Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Release.Build.0 = LIB Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/extern/libpng/include/projects/visualc71/libpng.vcproj b/extern/libpng/include/projects/visualc71/libpng.vcproj new file mode 100644 index 0000000000..e17f4f7a8d --- /dev/null +++ b/extern/libpng/include/projects/visualc71/libpng.vcproj @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extern/libpng/include/projects/visualc71/pngtest.vcproj b/extern/libpng/include/projects/visualc71/pngtest.vcproj new file mode 100644 index 0000000000..ac82ff9b7d --- /dev/null +++ b/extern/libpng/include/projects/visualc71/pngtest.vcproj @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extern/libpng/include/projects/visualc71/zlib.vcproj b/extern/libpng/include/projects/visualc71/zlib.vcproj new file mode 100644 index 0000000000..614b869e7f --- /dev/null +++ b/extern/libpng/include/projects/visualc71/zlib.vcproj @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extern/libpng/include/projects/vstudio/libpng/libpng.vcxproj b/extern/libpng/include/projects/vstudio/libpng/libpng.vcxproj new file mode 100644 index 0000000000..69779007cf --- /dev/null +++ b/extern/libpng/include/projects/vstudio/libpng/libpng.vcxproj @@ -0,0 +1,233 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + Win32Proj + libpng + + + + + DynamicLibrary + MultiByte + true + + + StaticLibrary + MultiByte + + + DynamicLibrary + true + MultiByte + + + StaticLibrary + MultiByte + + + + + + + + + + + + + + + + + + + false + + + $(ProjectName)15 + + + false + + $(ProjectName)15 + + + false + + + $(ProjectName)15 + + + false + + $(ProjectName)15 + + + + Use + Level4 + false + ProgramDatabase + EnableFastChecks + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + true + false + false + pngpriv.h + true + CompileAsC + true + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Disabled + + + Windows + true + zlib.lib + 15 + $(OutDir) + + + + + Use + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + true + false + false + pngpriv.h + true + CompileAsC + true + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + MultiThreadedDebug + + + Windows + true + + + + + Level4 + Use + ProgramDatabase + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + false + pngpriv.h + true + CompileAsC + true + false + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Full + + + Windows + true + true + true + zlib.lib + 15 + $(OutDir) + + + + + Level4 + Use + ProgramDatabase + MultiThreaded + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + false + pngpriv.h + true + CompileAsC + true + false + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Full + true + + + Windows + true + true + true + + + true + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + true + true + + + + + + diff --git a/extern/libpng/include/projects/vstudio/pnglibconf/pnglibconf.vcxproj b/extern/libpng/include/projects/vstudio/pnglibconf/pnglibconf.vcxproj new file mode 100644 index 0000000000..7c691c32d3 --- /dev/null +++ b/extern/libpng/include/projects/vstudio/pnglibconf/pnglibconf.vcxproj @@ -0,0 +1,60 @@ + + + + + Release + Win32 + + + + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + pnglibconf + + + + Application + false + true + MultiByte + + + + + + + + + + Build + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + copy ..\..\..\scripts\pnglibconf.h.prebuilt ..\..\..\pnglibconf.h + + + Generating pnglibconf.h + + + ..\..\..\pnglibconf.h + + + ..\..\..\scripts\pnglibconf.h.prebuilt + + + + + + + + diff --git a/extern/libpng/include/projects/vstudio/pngtest/pngtest.vcxproj b/extern/libpng/include/projects/vstudio/pngtest/pngtest.vcxproj new file mode 100644 index 0000000000..a03dca565f --- /dev/null +++ b/extern/libpng/include/projects/vstudio/pngtest/pngtest.vcxproj @@ -0,0 +1,219 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D} + Win32Proj + pngtest + + + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + false + + + + false + + + + false + + + + false + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + false + true + true + false + + + Console + true + true + true + UseLinkTimeCodeGeneration + libpng15.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + MultiThreaded + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + UseLinkTimeCodeGeneration + $(OutDir) + + + Executing PNG test program + $(OutDir)pngtest.exe ..\..\..\pngtest.png $(IntDir)pngout.png + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + + + + + diff --git a/extern/libpng/include/projects/vstudio/pngvalid/pngvalid.vcxproj b/extern/libpng/include/projects/vstudio/pngvalid/pngvalid.vcxproj new file mode 100644 index 0000000000..79fd1bd82b --- /dev/null +++ b/extern/libpng/include/projects/vstudio/pngvalid/pngvalid.vcxproj @@ -0,0 +1,219 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8} + Win32Proj + pngvalid + + + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + false + + + + false + + + + false + + + + false + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + MultiThreaded + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing PNG validation program + $(OutDir)pngvalid.exe ..\..\..\pngvalid.png $(IntDir)pngout.png + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + + + + + diff --git a/extern/libpng/include/projects/vstudio/readme.txt b/extern/libpng/include/projects/vstudio/readme.txt new file mode 100644 index 0000000000..482465d76f --- /dev/null +++ b/extern/libpng/include/projects/vstudio/readme.txt @@ -0,0 +1,64 @@ + +VisualStudio instructions + +libpng version 1.5.2 - March 31, 2011 + +Copyright (c) 1998-2010 Glenn Randers-Pehrson + +This code is released under the libpng license. +For conditions of distribution and use, see the disclaimer +and license in png.h + +This directory contains support for building libpng under MicroSoft +VisualStudio 2010. It may also work under later versions of VisualStudio. +You should be familiar with VisualStudio before using this directory. + +Initial preparations +==================== +You must enter some information in zlib.props before attempting to build +with this 'solution'. Please read and edit zlib.props first. You will +probably not be familiar with the contents of zlib.props - do not worry, +it is mostly harmless. + +This is all you need to do to build the 'release' and 'release library' +configurations. + +Debugging +========= +The release configurations default to /Ox optimization. Full debugging +information is produced (in the .pdb), but if you encounter a problem the +optimization may make it difficult to debug. Simply rebuild with a lower +optimization level (e.g. /Od.) + +Linking your application +======================== +Normally you should link against the 'release' configuration. This builds a +DLL for libpng 1.5 with the default runtime options used by Visual Studio +2010. In particular the runtime library is the "MultiThreaded DLL" version. +If you use Visual Studio defaults to build your application you will have no +problems. + +If you don't use the Visual Studio defaults your application must still be built +with the default runtime option (/MD). If, for some reason, it is not then your +application will crash inside libpng15.dll as soon as libpng tries to read +from a file handle you pass in. + +If you do not want to use the DLL, for example for a very small application, +the 'release library' configuration may be more appropriate. This is built +with a non-standard runtime library - the "MultiThreaded" version. When you +build your application it must be compiled with this option (/MT), otherwise +it will not build (if you are lucky) or crash (if you are not.) + +Stop reading here +================= +You have enough information to build a working application. + +Debug versions have limited support +=================================== +This solution includes limited support for debug versions of libpng. You +do not need these unless your own solution itself uses debug builds (it is +far more effective to debug on the release builds, there is no point building +a special debug build.) + +The debug build of libpng is minimally supported. Support for debug builds of +zlib is also minimal. You really don't want to do this. diff --git a/extern/libpng/include/projects/vstudio/vstudio.sln b/extern/libpng/include/projects/vstudio/vstudio.sln new file mode 100644 index 0000000000..115db4d95d --- /dev/null +++ b/extern/libpng/include/projects/vstudio/vstudio.sln @@ -0,0 +1,79 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\libpng.vcxproj", "{D6973076-9317-4EF2-A0B8-B7A18AC0713E}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngtest", "pngtest\pngtest.vcxproj", "{228BA965-50D5-42B2-8BCF-AFCC227E3C1D}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcxproj", "{64CE4900-97EA-2DD5-4226-F2E36FFF2867}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngvalid", "pngvalid\pngvalid.vcxproj", "{9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pnglibconf", "pnglibconf\pnglibconf.vcxproj", "{EB33566E-DA7F-4D28-9077-88C0B7C77E35}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Library|Win32 = Debug Library|Win32 + Debug|Win32 = Debug|Win32 + Release Library|Win32 = Release Library|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|Win32.Build.0 = Debug|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release Library|Win32.Build.0 = Release Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|Win32.ActiveCfg = Release|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|Win32.Build.0 = Release|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug|Win32.ActiveCfg = Debug|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug|Win32.Build.0 = Debug|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.Build.0 = Release Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.ActiveCfg = Release|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.Build.0 = Release|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.ActiveCfg = Debug|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.Build.0 = Debug|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.Build.0 = Release Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.ActiveCfg = Release|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.Build.0 = Release|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.Build.0 = Debug|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release Library|Win32.Build.0 = Release Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release|Win32.ActiveCfg = Release|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug Library|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug Library|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extern/libpng/include/projects/vstudio/zlib.props b/extern/libpng/include/projects/vstudio/zlib.props new file mode 100644 index 0000000000..5ee232340e --- /dev/null +++ b/extern/libpng/include/projects/vstudio/zlib.props @@ -0,0 +1,30 @@ + + + + + + + ..\..\..\..\zlib-1.2.4 + + diff --git a/extern/libpng/include/projects/vstudio/zlib/zlib.vcxproj b/extern/libpng/include/projects/vstudio/zlib/zlib.vcxproj new file mode 100644 index 0000000000..aa125defe0 --- /dev/null +++ b/extern/libpng/include/projects/vstudio/zlib/zlib.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + Win32Proj + + + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + true + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreadedDebug + TurnOffAllWarnings + ProgramDatabase + Disabled + true + + + MachineX86 + true + Windows + + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + TurnOffAllWarnings + ProgramDatabase + Disabled + true + + + MachineX86 + true + Windows + + + + + Level3 + ProgramDatabase + Full + true + true + false + true + true + true + MultiThreaded + + + MachineX86 + true + Windows + + + true + + + + + Level3 + ProgramDatabase + Full + true + true + false + true + true + true + + + MachineX86 + true + Windows + + + true + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;DEBUGZLIB_EXPORTS;%(PreprocessorDefinitions) + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + + diff --git a/extern/libpng/include/scripts/README.txt b/extern/libpng/include/scripts/README.txt new file mode 100644 index 0000000000..8f393fa38e --- /dev/null +++ b/extern/libpng/include/scripts/README.txt @@ -0,0 +1,77 @@ + +Makefiles for libpng version 1.5.2 - March 31, 2011 + +pnglibconf.h.prebuilt => Stores configuration settings + makefile.linux => Linux/ELF makefile + (gcc, creates libpng15.so.15.1.5.2) + makefile.gcc => Generic makefile (gcc, creates static libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files with + ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.acorn => Acorn makefile + makefile.aix => AIX/gcc makefile + makefile.amiga => Amiga makefile + makefile.atari => Atari makefile + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.beos => beos makefile + makefile.bor => Borland makefile (uses bcc) + makefile.cegcc => minge32ce for Windows CE makefile + makefile.darwin => Darwin makefile, can use on MacosX + makefile.dec => DEC Alpha UNIX makefile + makefile.dj2 => DJGPP 2 makefile + makefile.elf => Linux/ELF makefile symbol versioning, + (gcc, creates libpng15.so.15.1.5.2) + makefile.freebsd => FreeBSD makefile + makefile.gcc => Generic gcc makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64-bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) + makefile.intel => Intel C/C++ version 4.0 and later + makefile.mips => MIPS makefile + makefile.msc => Microsoft C makefile + makefile.netbsd => NetBSD/cc makefile, makes libpng.so. + makefile.openbsd => OpenBSD makefile + makefile.os2 => OS/2 Makefile (gcc and emx, requires libpng.def) + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.sggcc => Silicon Graphics (gcc, + creates libpng15.so.15.1.5.2) + makefile.sgi => Silicon Graphics IRIX makefile (cc, creates static lib) + makefile.solaris => Solaris 2.X makefile (gcc, + creates libpng15.so.15.1.5.2) + makefile.so9 => Solaris 9 makefile (gcc, + creates libpng15.so.15.1.5.2) + makefile.std => Generic UNIX makefile (cc, creates static libpng.a) + makefile.sunos => Sun makefile + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.tc3 => Turbo C 3.0 makefile + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and later + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC compiler + (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc) + +Other supporting scripts: + README.txt => This file + descrip.mms => VMS makefile for MMS or MMK + libpng-config-body.in => used by several makefiles to create libpng-config + libpng-config-head.in => used by several makefiles to create libpng-config + libpng.pc.in => Used by several makefiles to create libpng.pc + pngwin.rc => Used by the visualc6 and visualc71 projects. + pngwin.def => Used by makefile.os2 + pngwin.dfn => Used to maintain pngwin.def + SCOPTIONS.ppc => Used with smakefile.ppc + +checksym.awk => Used for maintaining pnglibconf.h +def.dfn => Used for maintaining pnglibconf.h +options.awk => Used for maintaining pnglibconf.h +pnglibconf.dfa => Used for maintaining pnglibconf.h +pnglibconf.mak => Used for maintaining pnglibconf.h +sym.dfn => Used for symbol versioning +symbols.def => Used for symbol versioning +symbols.dfn => Used for symbol versioning +vers.dfn => Used for symbol versioning + + +Further information can be found in comments in the individual makefiles. diff --git a/extern/libpng/include/scripts/SCOPTIONS.ppc b/extern/libpng/include/scripts/SCOPTIONS.ppc new file mode 100644 index 0000000000..2c3503e9eb --- /dev/null +++ b/extern/libpng/include/scripts/SCOPTIONS.ppc @@ -0,0 +1,7 @@ +OPTIMIZE +OPTPEEP +OPTTIME +OPTSCHED +AUTOREGISTER +PARMS=REGISTERS +INCLUDEDIR=hlp:ppc/include diff --git a/extern/libpng/include/scripts/checksym.awk b/extern/libpng/include/scripts/checksym.awk new file mode 100755 index 0000000000..ba4c99b564 --- /dev/null +++ b/extern/libpng/include/scripts/checksym.awk @@ -0,0 +1,161 @@ +#!/bin/awk -f +# Check a list of symbols against the master definition +# (official) list. Arguments: +# +# awk -f checksym.awk official-def list-to-check +# +# Output is a file in the current directory called 'symbols.new', +# stdout holds error messages. Error code indicates success or +# failure. +# +# NOTE: this is a pure, old fashioned, awk script. It will +# work with any awk + +BEGIN{ + err=0 + master="" # master file + official[1] = "" # defined symbols from master file + symbol[1] = "" # defined symbols from png.h + removed[1] = "" # removed symbols from png.h + lasto = 0 # last ordinal value from png.h + mastero = 0 # highest ordinal in master file + symbolo = 0 # highest ordinal in png.h + missing = "error"# log an error on missing symbols +} + +# Read existing definitions from the master file (the first +# file on the command line.) This must be a def file and it +# has definition lines (others are ignored) of the form: +# +# symbol @ordinal +# +master == "" { + master = FILENAME +} +FILENAME==master && NF==2 && $2~/^@/ && $1!~/^;/ { + o=0+substr($2,2) + if (o > 0) { + if (official[o] == "") { + official[o] = $1 + if (o > mastero) mastero = o + next + } else + print master ": duplicated symbol:", official[o] ":", $0 + } else + print master ": bad export line format:", $0 + err = 1 +} +FILENAME==master && $1==";missing" && NF==2{ + # This allows the master file to control how missing symbols + # are handled; symbols that aren't in either the master or + # the new file. Valid values are 'ignore', 'warning' and + # 'error' + missing = $2 +} +FILENAME==master { + next +} + +# Read new definitions, these are free form but the lines must +# just be symbol definitions. Lines will be commented out for +# 'removed' symbols, introduced in png.h using PNG_REMOVED rather +# than PNG_EXPORT. Use symbols.dfn or pngwin.dfn to generate the +# input file. +# +# symbol @ordinal # two fields, exported symbol +# ; symbol @ordinal # three fields, removed symbol +# ; @ordinal # two fields, the last ordinal +NF==2 && $1 == ";" && $2 ~ /^@[1-9][0-9]*$/ { # last ordinal + o=0+substr($2,2) + if (lasto == 0 || lasto == o) + lasto=o + else { + print "png.h: duplicated last ordinal:", lasto, o + err = 1 + } + next +} +NF==3 && $1 == ";" && $3 ~ /^@[1-9][0-9]*$/ { # removed symbol + o=0+substr($3,2) + if (removed[o] == "" || removed[o] == $2) { + removed[o] = $2 + if (o > symbolo) symbolo = o + } else { + print "png.h: duplicated removed symbol", o ": '" removed[o] "' != '" $2 "'" + err = 1 + } + next +} +NF==2 && $2 ~ /^@[1-9][0-9]*$/ { # exported symbol + o=0+substr($2,2) + if (symbol[o] == "" || symbol[o] == $1) { + symbol[o] = $1 + if (o > symbolo) symbolo = o + } else { + print "png.h: duplicated symbol", o ": '" symbol[o] "' != '" $1 "'" + err = 1 + } +} +{ + next # skip all other lines +} + +# At the end check for symbols marked as both duplicated and removed +END{ + if (symbolo > lasto) { + print "highest symbol ordinal in png.h,", symbolo ", exceeds last ordinal from png.h", lasto + err = 1 + } + if (mastero > lasto) { + print "highest symbol ordinal in", master ",", mastero ", exceeds last ordinal from png.h", lasto + err = 1 + } + unexported=0 + for (o=1; o<=lasto; ++o) { + if (symbol[o] == "" && removed[o] == "") { + if (unexported == 0) unexported = o + if (official[o] == "") { + # missing in export list too, so ok + if (o < lasto) continue + } + } + if (unexported != 0) { + # Symbols in the .def but not in the new file are errors, but + # the 'unexported' symbols aren't in either. By default this + # is an error too (see the setting of 'missing' at the start), + # but this can be reset on the command line or by stuff in the + # file - see the comments above. + if (missing != "ignore") { + if (o-1 > unexported) + print "png.h:", missing ": missing symbols:", unexported "-" o-1 + else + print "png.h:", missing ": missing symbol:", unexported + if (missing != "warning") + err = 1 + } + unexported = 0 + } + if (symbol[o] != "" && removed[o] != "") { + print "png.h: symbol", o, "both exported as '" symbol[o] "' and removed as '" removed[o] "'" + err = 1 + } else if (symbol[o] != official[o]) { + # either the symbol is missing somewhere or it changed + err = 1 + if (symbol[o] == "") + print "png.h: symbol", o, "is exported as '" official[o] "' in", master + else if (official[o] == "") + print "png.h: exported symbol", o, "'" symbol[o] "' not present in", master + else + print "png.h: exported symbol", o, "'" symbol[o] "' exists as '" official[o] "' in", master + } + + # Finally generate symbols.new + if (symbol[o] != "") + print " " symbol[o], "@" o > "symbols.new" + } + + if (err != 0) { + print "*** A new list is in symbols.new ***" + exit 1 + } +} diff --git a/extern/libpng/include/scripts/chkfmt b/extern/libpng/include/scripts/chkfmt new file mode 100755 index 0000000000..9da6475fd4 --- /dev/null +++ b/extern/libpng/include/scripts/chkfmt @@ -0,0 +1,137 @@ +#!/bin/sh +# +# Check the format of the source files in the current directory - checks for a +# line length of 80 characters max and no tab characters. +# +# Optionally arguments are files or directories to check. +# +# -v: output the long lines (makes fixing them easier) +# -e: spawn an editor for each file that needs a change ($EDITOR must be +# defined). When using -e the script MUST be run from an interactive +# command line. +verbose= +edit= +vers= +test "$1" = "-v" && { + shift + verbose=yes +} +test "$1" = "-e" && { + shift + if test -n "$EDITOR" + then + edit=yes + + # Copy the standard streams for the editor + exec 3>&0 4>&1 5>&2 + else + echo "chkfmt -e: EDITOR must be defined" >&2 + exit 1 + fi +} + +# Function to edit a single file - if the file isn't changed ask the user +# whether or not to continue. This stuff only works if the script is run from +# the command line (otherwise, don't specify -e or you will be sorry). +doed(){ + cp "$file" "$file".orig + "$EDITOR" "$file" 0>&3 1>&4 2>&5 3>&- 4>&- 5>&- || exit 1 + if cmp -s "$file".orig "$file" + then + rm "$file".orig + echo -n "$file: file not changed, type anything to continue: " >&5 + read ans 0>&3 + test -n "$ans" || return 1 + fi + return 0 +} + +# In beta versions the version string which appears in files can be a little +# long and cause spuriously overlong lines. To avoid this subtitute the version +# string with a 'standard' version a.b.cc before checking for long lines. +if test -r png.h +then + vers="`sed -n -e \ + 's/^#define PNG_LIBPNG_VER_STRING .\([0-9]\.[0-9]\.[0-9][0-9a-z]*\).$/\1/p' \ + png.h`" + echo "chkfmt: checking version $vers" +fi +if test -z "$vers" +then + echo "chkfmt: png.h not found, ignoring version number" >&2 +fi + +test -n "$1" || set -- . +find "$@" \( -type d \( -name '.git' -o -name '.libs' -o -name 'projects' \) \ + -prune \) -o \( -type f \ + ! -name '*.[oa]' ! -name '*.l[oa]' ! -name '*.png' ! -name '*.out' \ + ! -name '*.jpg' ! -name '*.patch' ! -name '*.obj' ! -name '*.exe' \ + ! -name '*.com' ! -name '*.tar.*' ! -name '*.zip' ! -name '*.ico' \ + ! -name '*.res' ! -name '*.rc' ! -name '*.mms' ! -name '*.rej' \ + ! -name '*.dsp' ! -name '*.orig' ! -name '*.dfn' ! -name '*.swp' \ + ! -name '~*' ! -name '*.3' \ + ! -name 'missing' ! -name 'mkinstalldirs' ! -name 'depcomp' \ + ! -name 'aclocal.m4' ! -name 'install-sh' ! -name 'Makefile.in' \ + ! -name 'ltmain.sh' ! -name 'config*' -print \) | { + st=0 + while read file + do + case "$file" in + *.mak|*[Mm]akefile.*|*[Mm]akefile) + # Makefiles require tabs, dependency lines can be this long. + check_tabs= + line_length=100;; + *.awk) + # Includes literal tabs + check_tabs= + # The following is arbitrary + line_length=132;; + *contrib/*/*.[ch]) + check_tabs=yes + line_length=96;; + *) + check_tabs=yes + line_length=80;; + esac + + # Note that vers can only contain 0-9, . and a-z + if test -n "$vers" + then + sed -e "s/$vers/a.b.cc/g" "$file" >"$file".$$ + else + cp "$file" "$file".$$ + fi + splt="`fold -$line_length "$file".$$ | diff -c "$file".$$ -`" + rm "$file".$$ + + if test -n "$splt" + then + echo "$file: lines too long" + st=1 + if test -n "$EDITOR" -a -n "$edit" + then + doed "$file" || exit 1 + elif test -n "$verbose" + then + echo "$splt" + fi + fi + if test -n "$check_tabs" + then + tab="`tr -c -d '\t' <"$file"`" + if test -n "$tab" + then + echo "$file: file contains tab characters" + st=1 + if test -n "$EDITOR" -a -n "$edit" + then + doed "$file" || exit 1 + elif test -n "$verbose" + then + echo "$splt" + fi + fi + fi + done + exit $st +} diff --git a/extern/libpng/include/scripts/def.dfn b/extern/libpng/include/scripts/def.dfn new file mode 100644 index 0000000000..d918d4c3c8 --- /dev/null +++ b/extern/libpng/include/scripts/def.dfn @@ -0,0 +1,38 @@ +/* def.dfn - define format of libpng.def + * + * Last changed in libpng version 1.5.0 [(PENDING RELEASE)] + * Copyright (c) 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* These macros exist to make the header and trailer shorter below: */ +#define S PNG_DEFN_MAGIC +#define E PNG_DEFN_END + +/* Write the export file header: */ +S-;---------------------------------------------------------------E +S-; LIBPNG module definition file for OS/2-E +S-;---------------------------------------------------------------E +S--E +S-; If you give the library an explicit name one or other files-E +S-; may need modifying to support the new name on one or more-E +S-; systems.-E +S-LIBRARY-E +S-OS2 DESCRIPTION "PNG image compression library"-E +S-OS2 CODE PRELOAD MOVEABLE DISCARDABLE-E +S--E +S-EXPORTS-E +S-;Version 1.5.0beta58-E + +/* NOTE: @@@ is interpreted by the calling script as a signal to + * join the two things on either side, so we can do symbol + * substitution within the name, regular C ## joins the pp-tokens, + * not their final values. + */ +#define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_DEFN_MAGIC- SYMBOL_PREFIX @@@ name-PNG_DEFN_END + +#include "../png.h" diff --git a/extern/libpng/include/scripts/descrip.mms b/extern/libpng/include/scripts/descrip.mms new file mode 100644 index 0000000000..99ea1abccd --- /dev/null +++ b/extern/libpng/include/scripts/descrip.mms @@ -0,0 +1,52 @@ + +cc_defs = /inc=$(ZLIBSRC) +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + + + +OBJS = png.obj, pngset.obj, pngget.obj, pngrutil.obj, pngtrans.obj,\ + pngwutil.obj, pngread.obj, pngmem.obj, pngwrite.obj, pngrtran.obj,\ + pngwtran.obj, pngrio.obj, pngwio.obj, pngerror.obj, pngpread.obj + + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : pngtest.exe libpng.olb + @ write sys$output " pngtest available" + +libpng.olb : libpng.olb($(OBJS)) + @ write sys$output " Libpng available" + + +pngtest.exe : pngtest.obj libpng.olb + link pngtest,libpng.olb/lib,$(ZLIBSRC)libz.olb/lib + +test : pngtest.exe + run pngtest + +clean : + delete *.obj;*,*.exe; + + +# Other dependencies. +png.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngpread.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngset.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngget.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngread.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrtran.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrutil.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngerror.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngmem.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrio.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwio.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngtrans.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwrite.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwtran.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwutil.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h + +pngtest.obj : png.h, pngconf.h diff --git a/extern/libpng/include/scripts/libpng-config-body.in b/extern/libpng/include/scripts/libpng-config-body.in new file mode 100755 index 0000000000..b466432d54 --- /dev/null +++ b/extern/libpng/include/scripts/libpng-config-body.in @@ -0,0 +1,96 @@ + +usage() +{ + cat < libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo ccopts=\"-xtarget=ultra\"; \ + echo ldopts=\"-xtarget=ultra\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -L$(ZLIBLIB) -R$(ZLIBLIB) -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) $(SUN_CC_FLAGS) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd -L$(DL) -R$(DL) `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(SUN_CC_FLAGS) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.64sunu b/extern/libpng/include/scripts/makefile.64sunu new file mode 100644 index 0000000000..a0331d670e --- /dev/null +++ b/extern/libpng/include/scripts/makefile.64sunu @@ -0,0 +1,241 @@ +# makefile for libpng on Solaris 2.x with cc +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +SUN_CC_FLAGS=-fast -xtarget=ultra -xarch=v9 +SUN_LD_FLAGS=-fast -xtarget=ultra -xarch=v9 + +# where make install puts libpng.a, libpng15.so and libpng15/png.h +prefix=/a +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/lib +ZLIBINC=/usr/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) $(SUN_CC_FLAGS) \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +include scripts/pnglibconf.mak +DELETE = $(RM_F) +DFNFLAGS = $(DEFS) $(CPPFLAGS) + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo ccopts=\"-xtarget=ultra -xarch=v9\"; \ + echo ldopts=\"-xtarget=ultra -xarch=v9\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -L$(ZLIBLIB) -R$(ZLIBLIB) -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) $(SUN_CC_FLAGS) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd -L$(DL) -R$(DL) `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(SUN_CC_FLAGS) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.acorn b/extern/libpng/include/scripts/makefile.acorn new file mode 100644 index 0000000000..00b8fb5b35 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.acorn @@ -0,0 +1,57 @@ +# Project: libpng + + +# Toolflags: +CCflags = -c -depend !Depend -IC:,Zlib: -g -throwback -DRISCOS -fnah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# Final targets: +@.libpng-lib: @.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \ + @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngrtran \ + @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil + LibFile $(LibFileflags) @.o.png @.o.pngerror @.o.pngrio @.o.pngrtran \ + @.o.pngmem @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngwio \ + @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil +@.mm-libpng-lib: @.mm.png @.mm.pngerror @.mm.pngrio @.mm.pngwio @.mm.pngmem \ + @.mm.pngpread @.mm.pngset @.mm.pngget @.mm.pngread @.mm.pngrtran \ + @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite @.mm.pngwtran @.mm.pngwutil + LibFile $(LibFileflags) @.mm.png @.mm.pngerror @.mm.pngrio \ + @.mm.pngwio @.mm.pngmem @.mm.pngpread @.mm.pngset @.mm.pngget \ + @.mm.pngread @.mm.pngrtran @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite \ + @.mm.pngwtran @.mm.pngwutil + + +# User-editable dependencies: +# (C) Copyright 1997 Tom Tanner +Test: @.pngtest + .pngtest + @remove .pngtest + +#It would be nice if you could stop "make" listing from here on! +@.pngtest: @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib + Link $(Linkflags) @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib + +.SUFFIXES: .o .mm .c + +.c.mm: + MemCheck.CC cc $(ccflags) -o $@ LibPng:$< +.c.o: + cc $(ccflags) -o $@ $< + +# See scripts.mak.libpngconf for how to generate this: +@.h.libpngconf: @.scripts.h.libpngconf + copy @.scripts.h.libpngconf $@ + +# Static dependencies: +@.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \ +@.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngrtran \ +@.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil \ +@.o.pngtest: @.h.libpngconf + + +# Dynamic dependencies: diff --git a/extern/libpng/include/scripts/makefile.aix b/extern/libpng/include/scripts/makefile.aix new file mode 100644 index 0000000000..bb4c40d4b0 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.aix @@ -0,0 +1,121 @@ +# makefile for libpng using gcc (generic, static library) +# Copyright (C) 2002, 2006-2009 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# Copyright (C) 2000 Marc O. Gloor (AIX support added, from makefile.gcc) +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = gcc +LD = $(CC) +AR_RC = ar rcs +MKDIR_P = mkdir -p +RANLIB = ranlib +RM_F = rm -f +LN_SF = ln -f -s + +LIBNAME=libpng15 +PNGMAJ = 15 + +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) + +CDEBUG = -g -DPNG_DEBUG=5 +LDDEBUG = +CRELEASE = -O2 +LDRELEASE = -s +WARNMORE=-W -Wall +CFLAGS = -I$(ZLIBINC) $(WARNMORE) $(CRELEASE) +LDFLAGS = -L. -L$(ZLIBLIB) -lpng15 -lz -lm $(LDRELEASE) + +# File extensions +O=.o +A=.a +E= + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +# Targets +all: $(LIBNAME)$(A) pngtest$(E) + +include scripts/pnglibconf.mak +REMOVE = $(RM_F) +DFNFLAGS = $(DEFS) $(CPPFLAGS) + +$(LIBNAME)$(A): $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +test: pngtest$(E) + ./pngtest$(E) + +pngtest$(E): pngtest$(O) $(LIBNAME)$(A) + $(LD) -o $@ pngtest$(O) $(LDFLAGS) + +install: $(LIBNAME)$(A) + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DI)/$(LIBNAME)/png.h + -@$(RM_F) $(DI)/$(LIBNAME)/pngconf.h + -@$(RM_F) $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h + -@$(RM_F) $(DI)/pngconf.h + -@$(RM_F) $(DI)/pnglibconf.h + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h \ + $(DI)/$(LIBNAME)/pngconf.h \ + $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) -r $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + -@$(RM_F) $(DL)/$(LIBNAME)$(A) + -@$(RM_F) $(DL)/libpng$(A) + cp $(LIBNAME)$(A) $(DL)/$(LIBNAME)$(A) + chmod 644 $(DL)/$(LIBNAME)$(A) + (cd $(DL); $(LN_SF) $(LIBNAME)$(A) libpng$(A)) + (cd $(DI); $(LN_SF) libpng/* .;) + +clean: + $(RM_F) *.o $(LIBNAME)$(A) pngtest pngout.png pnglibconf.h + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.amiga b/extern/libpng/include/scripts/makefile.amiga new file mode 100644 index 0000000000..228b5c22a7 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.amiga @@ -0,0 +1,56 @@ +# Commodore Amiga Makefile +# makefile for libpng and SAS C V6.5x compiler +# Copyright (C) 1995-2000 Wolf Faust +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Location/path of zlib include files +ZLIB=/zlib +#compiler +CC=sc +#compiler flags +# WARNING: a bug in V6.51 causes bad code with OPTGO +# So use V6.55 or set NOOPTGO!!!!!!!!! +CFLAGS= NOSTKCHK PARMS=REG OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL\ + OPTLOOP OPTRDEP=4 OPTDEP=4 OPTCOMP=4 INCLUDEDIR=$(ZLIB) \ + DEFINE=PNG_INTERNAL +#linker flags +LDFLAGS= SD ND BATCH +#link libs +LDLIBS= libpng.lib libgz.lib LIB:scm.lib LIB:sc.lib Lib:amiga.lib +# linker +LN= slink +# file deletion command +RM= delete quiet +# file copy command? +CP= copy +# library (.lib) file creation command +AR= oml +# make directory command +MKDIR= makedir + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.lib pngtest + +libpng.lib: $(OBJS) +-$(RM) libpng.lib +$(AR) libpng.lib r $(OBJS) + +$(OBJS): pngpriv.h png.h pngconf.h pnglibconf.h pnginfo.h pngstruct.h pngdebug.h + +pnglibconf.h: scripts/pnglibconf.h.prebuilt +$(CP) scripts/pnglibconf.h.prebuilt pnglibconf.h + +pngtest: pngtest.o libpng.lib +$(LN) libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo libs=\"-lpng15 -lz \"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + cp $(LIBSO)* /boot/home/config/lib + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -nostart -Wl,-soname,$(LIBSOMAJ) -o \ + $(LIBSOMAJ) $(OBJSDLL) $(LDFLAGS) + +pngtest: pngtest.o $(LIBSO) + $(CC) -L$(ZLIBLIB) -L. -lz -lpng15 -o pngtest pngtest.o + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl,-rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtesti \ + pnglibconf.h libpng.pc + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.bor b/extern/libpng/include/scripts/makefile.bor new file mode 100644 index 0000000000..96d5e861a3 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.bor @@ -0,0 +1,161 @@ +# Makefile for libpng +# 16-bit Borland C++ (Note: All modules are compiled in C mode) +# To build the library, do: +# "make -fmakefile.bor -DMODEL=c" +# or: "make -fmakefile.bor -DMODEL=l" +# +# ------------ Borland C++ ------------ + +### Absolutely necessary for this makefile to work +.AUTODEPEND + +## Where zlib.h, zconf.h and zlib_MODEL.lib are +ZLIB_DIR=..\zlib + +## Compiler, linker and lib stuff +CC=bcc +LD=bcc +LIB=tlib + +!ifndef MODEL +MODEL=l +!endif + +MODEL_ARG=-m$(MODEL) + +#TARGET_CPU=3 +# 2 = 286, 3 = 386, etc. +!ifndef TARGET_CPU +TARGET_CPU=2 +!endif + +# Use this if you don't want Borland's fancy exception handling +# (for Borland C++ 4.0 or later) +#NOEHLIB=noeh$(MODEL).lib + +!ifdef DEBUG +CDEBUG=-v +LDEBUG=-v +!else +CDEBUG= +LDEBUG= +!endif + +# STACKOFLOW=1 +!ifdef STACKOFLOW +CDEBUG=$(CDEBUG) -N +LDEBUG=$(LDEBUG) -N +!endif + +# -X- turn on dependency generation in the object file +# -w set all warnings on +# -O2 optimize for speed +# -Z global optimization +CFLAGS=-O2 -Z -X- -w -I$(ZLIB_DIR) -$(TARGET_CPU) $(MODEL_ARG) $(CDEBUG) + +# -M generate map file +LDFLAGS=-M -L$(ZLIB_DIR) $(MODEL_ARG) $(LDEBUG) + +## Variables + +OBJS = \ + png.obj \ + pngerror.obj \ + pngget.obj \ + pngmem.obj \ + pngpread.obj \ + pngread.obj \ + pngrio.obj \ + pngrtran.obj \ + pngrutil.obj \ + pngset.obj \ + pngtrans.obj \ + pngwio.obj \ + pngwrite.obj \ + pngwtran.obj \ + pngwutil.obj + +LIBOBJS = \ + +png.obj \ + +pngerror.obj \ + +pngget.obj \ + +pngmem.obj \ + +pngpread.obj \ + +pngread.obj \ + +pngrio.obj \ + +pngrtran.obj \ + +pngrutil.obj \ + +pngset.obj \ + +pngtrans.obj \ + +pngwio.obj \ + +pngwrite.obj \ + +pngwtran.obj \ + +pngwutil.obj + +LIBNAME=libpng$(MODEL).lib + +## Implicit rules + +# Braces let make "batch" calls to the compiler, +# 2 calls instead of 12; space is important. +.c.obj: + $(CC) $(CFLAGS) -c {$*.c } + +.c.exe: + $(CC) $(CFLAGS) $(LDFLAGS) $*.c $(LIBNAME) zlib_$(MODEL).lib $(NOEHLIB) + +## Major targets + +all: libpng pngtest + +# try !inlude scripts\pnglibconf.mak for more options +pnglibconf.h: scripts\pnglibconf.h.prebuilt + copy scripts\pnglibconf.h.prebuilt $@ + +libpng: $(LIBNAME) + +pngtest: pngtest$(MODEL).exe + +test: pngtest$(MODEL).exe + pngtest$(MODEL) + +## Minor Targets + +png.obj: png.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.obj: pngerror.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.obj: pngget.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.obj: pngmem.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.obj: pngpread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.obj: pngread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.obj: pngrio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.obj: pngrtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.obj: pngrutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.obj: pngset.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.obj: pngtrans.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.obj: pngwio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.obj: pngwrite.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.obj: pngwtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.obj: pngwutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +$(LIBNAME): $(OBJS) + -del $(LIBNAME) + $(LIB) $(LIBNAME) @&&| +$(LIBOBJS), libpng$(MODEL) +| + +pngtest$(MODEL).obj: pngtest.c png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) -opngtest$(MODEL) -c pngtest.c + +pngtest$(MODEL).exe: pngtest$(MODEL).obj + $(LD) $(LDFLAGS) pngtest$(MODEL).obj $(LIBNAME) zlib_$(MODEL).lib $(NOEHLIB) + +# Clean up anything else you want +clean: + -del pnglibconf.h + -del *.obj + -del *.exe + -del *.lib + -del *.lst + -del *.map + +# End of makefile for libpng diff --git a/extern/libpng/include/scripts/makefile.cegcc b/extern/libpng/include/scripts/makefile.cegcc new file mode 100644 index 0000000000..28fb3ac6ad --- /dev/null +++ b/extern/libpng/include/scripts/makefile.cegcc @@ -0,0 +1,116 @@ +# Makefile for creating Windows CE release archives, with the +# mingw32ce compiler. + +# Last updated: 22-Jul-2008 + +# Copyright (C) 2008 Vincent Torri + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# To get some help, type +# +# make help +# +# To create the archives +# +# make +# +# To remove everything, type: +# +# make clean + +VERMAJ = 1 +VERMIN = 5 +VERMIC = 2 +VER = $(VERMAJ).$(VERMIN).$(VERMIC) +NAME = libpng +PACKAGE = $(NAME)-$(VER) + +BIN = libpng15-0.dll +LIB = libpng15.a libpng15.dll.a libpng.a libpng.dll.a +INCLUDE = png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +PC = libpng15.pc libpng.pc + +MANIFESTVERBIN = "Libpng-$(VER): Binary files" +MANIFESTVERDEV = "Libpng-$(VER): Developer files" +MANIFESTVERDESC = "Libpng: the official PNG reference library" + +all: $(NAME) + +$(NAME): remove-old copy-src compilation copy manifest archive + @echo " * Removal of the directories" + @rm -rf $(PACKAGE)/ $(PACKAGE)-bin/ $(PACKAGE)-dev/ + +remove-old: + @echo " * Removal of the old files" + @rm -rf $(PACKAGE)-bin* + @rm -rf $(PACKAGE)-dev* + +copy-src: + @echo " * Copy of source files" + @cp -R ../src/$(PACKAGE) . + @echo " * Creation of directories and files" + @mkdir -p $(PACKAGE)-bin/bin + @mkdir -p $(PACKAGE)-bin/manifest + @mkdir -p $(PACKAGE)-dev/lib/pkgconfig + @mkdir -p $(PACKAGE)-dev/include/$(NAME)$(VERMAJ)$(VERMIN) + @mkdir -p $(PACKAGE)-dev/manifest + @touch $(PACKAGE)-bin/manifest/$(PACKAGE)-bin.mft + @touch $(PACKAGE)-bin/manifest/$(PACKAGE)-bin.ver + @touch $(PACKAGE)-dev/manifest/$(PACKAGE)-dev.mft + @touch $(PACKAGE)-dev/manifest/$(PACKAGE)-dev.ver + +compilation: + @echo " * Compilation of $(PACKAGE)" + cd $(PACKAGE) && CPPFLAGS="$(CPPFLAGS) -DPNG_CONSOLE_IO_SUPPORTED -D_WIN32_WCE=0x0420" \ + CFLAGS="$(CFLAGS) -mms-bitfields -O3 -pipe -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -Wl,--enable-auto-import -Wl,-s" \ + ./configure --prefix=/opt/wince --host=arm-mingw32ce && make + +copy: + @echo " * Copy of binary and development files" + @for i in $(BIN); do \ + cp $(PACKAGE)/.libs/$$i $(PACKAGE)-bin/bin; \ + done + @for i in $(LIB); do \ + cp $(PACKAGE)/.libs/$$i $(PACKAGE)-dev/lib; \ + done + @for i in $(INCLUDE); do \ + cp $(PACKAGE)/$$i $(PACKAGE)-dev/include/$(NAME)$(VERMAJ)$(VERMIN); \ + done + @for i in $(PC); do \ + cp $(PACKAGE)/$$i $(PACKAGE)-dev/lib/pkgconfig; \ + done + +manifest: + @echo " * Creation of the manifest" + @cd $(PACKAGE)-bin && find * >> manifest/$(PACKAGE)-bin.mft + @cd $(PACKAGE)-bin && \ + echo $(MANIFESTVERBIN) >> manifest/$(PACKAGE)-bin.ver && \ + echo $(MANIFESTVERDESC) >> manifest/$(PACKAGE)-bin.ver + @cd $(PACKAGE)-dev && find * >> manifest/$(PACKAGE)-dev.mft + @cd $(PACKAGE)-dev && \ + echo $(MANIFESTVERDEV) >> manifest/$(PACKAGE)-dev.ver && \ + echo $(MANIFESTVERDESC) >> manifest/$(PACKAGE)-dev.ver + +archive: + @echo " * Creation of the archives" + @tar cf $(PACKAGE)-bin.tar $(PACKAGE)-bin + @bzip2 -9 $(PACKAGE)-bin.tar + @tar cf $(PACKAGE)-dev.tar $(PACKAGE)-dev + @bzip2 -9 $(PACKAGE)-dev.tar + +clean: + @echo " * Cleaning" + @rm -rf $(PACKAGE)* + +help: + @echo + @echo "To create the archives, type:" + @echo " make" + @echo + @echo "To remove everything, type:" + @echo " make clean" + @echo diff --git a/extern/libpng/include/scripts/makefile.darwin b/extern/libpng/include/scripts/makefile.darwin new file mode 100644 index 0000000000..aaec54dcb3 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.darwin @@ -0,0 +1,219 @@ +# makefile for libpng on Darwin / Mac OS X +# Copyright (C) 2002, 2004, 2006, 2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 2001 Christoph Pfisterer +# derived from makefile.linux: +# Copyright (C) 1998, 1999 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where "make install" puts libpng.a, libpng15.dylib, png.h, pngconf.h, +# and pnglibconf.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).dylib +LIBSOMAJ=$(LIBNAME).$(PNGMAJ).dylib +LIBSOREL=$(LIBNAME).$(PNGMAJ).$(RELEASE).dylib +OLDSO=libpng.dylib + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops +CFLAGS=-I$(ZLIBINC) -W -Wall -O -funroll-loops +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fno-common -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -dynamiclib \ + -install_name $(LIBPATH)/$(LIBSOMAJ) \ + -current_version 15 -compatibility_version 15 \ + -o $(LIBSOMAJ) \ + $(OBJSDLL) -L$(ZLIBLIB) -lz + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + $(RANLIB) $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + libpng.pc $(LIBNAME).*dylib pngtesti pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.dec b/extern/libpng/include/scripts/makefile.dec new file mode 100644 index 0000000000..5301d87d33 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.dec @@ -0,0 +1,202 @@ +# makefile for libpng on DEC Alpha Unix +# Copyright (C) 2000-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +PNGMAJ = 15 +LIBNAME = libpng15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir +LN_SF=ln -f -s +RANLIB=ranlib +RM_F=/bin/rm -f + +# where make install puts libpng.a and png.h +prefix=/usr/local +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CFLAGS=-std -w1 -I$(ZLIBINC) -O # -g -DPNG_DEBUG=1 +LDFLAGS=-L$(ZLIBLIB) -rpath $(ZLIBLIB) libpng.a -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: $(LIBSO) libpng.a pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-std\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(CC) -shared -o $@ $(OBJS) -L$(ZLIBLIB) \ + -soname $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@/bin/rm -f $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@/bin/rm -f $(DI)/libpng + (cd $(DI); $(LN_SF)(LIBNAME) libpng; $(LN_SF)(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@/bin/rm -f $(DL)/libpng.a + (cd $(DL); $(LN_SF)(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@/bin/rm -f $(DM)/man3/libpng.3 + -@/bin/rm -f $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@/bin/rm -f $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@/bin/rm -f $(DB)/libpng-config + -@/bin/rm -f $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF)(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -w1 -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -w1 -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -R$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + /bin/rm -f *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.dj2 b/extern/libpng/include/scripts/makefile.dj2 new file mode 100644 index 0000000000..87a05a364a --- /dev/null +++ b/extern/libpng/include/scripts/makefile.dj2 @@ -0,0 +1,62 @@ +# DJGPP (DOS gcc) makefile for libpng +# Copyright (C) 2002, 2006, 2009-2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install will put libpng.a and png.h +#prefix=/usr/local +prefix=. +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +CC=gcc +CFLAGS=-I../zlib -O -DPNG_NO_SNPRINTF +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm + +RANLIB=ranlib + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o pngwtran.o \ + pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + coff2exe pngtest + +test: pngtest + ./pngtest +clean: + rm -f *.o libpng.a pngtest pngout.png pnglibconf.h + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.elf b/extern/libpng/include/scripts/makefile.elf new file mode 100644 index 0000000000..5af43b1845 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.elf @@ -0,0 +1,263 @@ +# makefile for libpng.a and libpng15.so on Linux ELF with gcc +# Copyright (C) 1998, 1999, 2002, 2006, 2008, 2010-2011 Greg Roelofs +# and Glenn Randers-Pehrson +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Modified for Debian by Junichi Uekawa and Josselin Mouette +# Major modifications are: +# * link libpng explicitly with libz and libm +# * $(OLDSO).15 is a symlink rather than a different library +# * versioned symbols + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so +OLDSOMAJ=libpng.so.15 + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng15.a, libpng15.so*, +# libpng15/png.h, libpng15/pngconf.h, and libpng15/pnglibconf.h +# Prefix must be a full pathname. +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located. +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include +# ZLIBLIB=../zlib +# ZLIBINC=../zlib + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-W -Wall -D_REENTRANT -O2 \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 + +LDFLAGS=-L. -lpng15 +LDFLAGS_A=libpng.a -lz -lm +LIBADDFLAGS=-lz -lm + + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest pngtest-static libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng.syms: png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) -E -DPNG_BUILDSYMS -DPNG_INTERNAL png.h |\ + awk -F '[\t [\\]();]' -v PNGMAJ=$(PNGMAJ) 'BEGIN{printf("PNG15_%s {global:\n",PNGMAJ)}\ + { for (i=1;i+2<=NF;++i)\ + if ($$(i)=="PNG_FUNCTION_EXPORT" && $$(i+2)=="END")\ + print $$(i+1) ";";\ + for (i=1;i+1<=NF;++i)\ + if ($$(i)=="PNG_DATA_EXPORT")\ + print $$(i+1) ";";}\ + END{print "local: *; };"}' >$@.new + $(RM_F) $@ + mv $@.new $@ + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"\"; \ + echo R_opts=\"\"; \ + echo libs=\"-lpng15\"; \ + echo all_libs=\"-lpng15 $(LIBADDFLAGS)\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) libpng.syms + $(CC) -shared -Wl,-soname,$(LIBSOMAJ) \ + -Wl,-version-script,libpng.syms \ + -o $(LIBSOMAJ) \ + $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +pngtest-static: pngtest.o libpng.a + $(CC) -o pngtest-static $(CFLAGS) pngtest.o $(LDFLAGS_A) + +test: pngtest pngtest-static + @echo "" + @echo " Running pngtest dynamically linked with $(LIBSO):" + @echo "" + LD_LIBRARY_PATH=".:${LD_LIBRARY_PATH}" ./pngtest + @echo "" + @echo " Running pngtest statically linked with libpng.a:" + @echo "" + ./pngtest-static + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl, -rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a libpng.syms pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.freebsd b/extern/libpng/include/scripts/makefile.freebsd new file mode 100644 index 0000000000..994608c993 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.freebsd @@ -0,0 +1,53 @@ +# makefile for libpng under FreeBSD +# Copyright (C) 2002, 2007, 2009 Glenn Randers-Pehrson and Andrey A. Chernov +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +PREFIX?= /usr/local +SHLIB_VER?= 15 + +LIB= png +SHLIB_MAJOR= ${SHLIB_VER} +SHLIB_MINOR= 0 +NOPROFILE= YES +NOOBJ= YES + +# where make install puts libpng.a and png.h +DESTDIR= ${PREFIX} +LIBDIR= /lib +INCS= png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +INCSDIR= /include/libpng +INCDIR= ${INCSDIR} # for 4.x bsd.lib.mk +MAN= libpng.3 libpngpf.3 png.5 +MANDIR= /man/man +SYMLINKS= libpng/png.h ${INCSDIR}/../png.h \ + libpng/pngconf.h ${INCSDIR}/../pngconf.h \ + libpng/pnglibconf.h ${INCSDIR}/../pnglibconf.h +LDADD+= -lm -lz +DPADD+= ${LIBM} ${LIBZ} + +CFLAGS+= -I. + +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c + +pngtest: pngtest.o libpng.a + ${CC} ${CFLAGS} -L. -static -o pngtest pngtest.o -lpng -lz -lm + +CLEANFILES= pngtest pngtest.o pngout.png + +test: pngtest + ./pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +.include diff --git a/extern/libpng/include/scripts/makefile.gcc b/extern/libpng/include/scripts/makefile.gcc new file mode 100644 index 0000000000..2e5b611367 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.gcc @@ -0,0 +1,87 @@ +# makefile for libpng using gcc (generic, static library) +# Copyright (C) 2008 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = gcc +LD = $(CC) +AR_RC = ar rcs +RANLIB = ranlib +RM_F = rm -f + +CDEBUG = -g -DPNG_DEBUG=5 +LDDEBUG = +CRELEASE = -O2 +LDRELEASE = -s +#CFLAGS = -W -Wall $(CDEBUG) +CFLAGS = -W -Wall $(CRELEASE) +#LDFLAGS = $(LDDEBUG) +LDFLAGS = $(LDRELEASE) +LIBS = -lz -lm + +# File extensions +O=.o +A=.a +EXE= + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +# Targets +all: static + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +.c$(O): + $(CC) -c $(CFLAGS) -I$(ZLIBINC) $< + +static: libpng$(A) pngtest$(EXE) + +shared: + @echo This is a generic makefile that cannot create shared libraries. + @echo Please use a configuration that is specific to your platform. + @false + +libpng$(A): $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +test: pngtest$(EXE) + ./pngtest$(EXE) + +pngtest$(EXE): pngtest$(O) libpng$(A) + $(LD) $(LDFLAGS) -L$(ZLIBLIB) -o $@ pngtest$(O) libpng$(A) $(LIBS) + +clean: + $(RM_F) *$(O) libpng$(A) pngtest$(EXE) pngout.png pnglibconf.h + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.hp64 b/extern/libpng/include/scripts/makefile.hp64 new file mode 100644 index 0000000000..b5b631d11c --- /dev/null +++ b/extern/libpng/include/scripts/makefile.hp64 @@ -0,0 +1,224 @@ +# makefile for libpng, HPUX (10.20 and 11.00) using the ANSI/C product. +# Copyright (C) 1999-2002, 2006, 2009, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42 +# contributed by Jim Rice and updated by Chris Schleicher, Hewlett Packard +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +CFLAGS=-I$(ZLIBINC) -O -Ae -Wl,+vnocompatwarnings +DD64 \ +-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +Z -DHAVE_UNISTD_H -DUSE_MMAP +# Caution: be sure you have built zlib with the same CFLAGS. +CCFLAGS=-I$(ZLIBINC) -O -Ae -Wl,+vnocompatwarnings +DD64 \ +-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +Z -DHAVE_UNISTD_H -DUSE_MMAP + +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +# where make install puts libpng.a, libpng15.sl, and png.h +prefix=/opt/libpng +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) +z -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-Ae +DA1.1 +DS2.0\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.hpgcc b/extern/libpng/include/scripts/makefile.hpgcc new file mode 100644 index 0000000000..3fe21177a4 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.hpgcc @@ -0,0 +1,230 @@ +# makefile for libpng on HP-UX using GCC with the HP ANSI/C linker. +# Copyright (C) 2002, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 2001, Laurent faillie +# Copyright (C) 1998, 1999 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +CC=gcc +LD=ld +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng.a, $(OLDSO)*, png.h, pngconf.h +# and pnglibconf.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops -DPNG_NO_MMX_CODE \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 +#LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl,-rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.hpux b/extern/libpng/include/scripts/makefile.hpux new file mode 100644 index 0000000000..650ab4f662 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.hpux @@ -0,0 +1,221 @@ +# makefile for libpng, HPUX (10.20 and 11.00) using the ANSI/C product. +# Copyright (C) 1999-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42 +# contributed by Jim Rice and updated by Chris Schleicher, Hewlett Packard +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where make install puts libpng.a, libpng15.sl, and png.h +prefix=/opt/libpng +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +CFLAGS=-I$(ZLIBINC) -O -Ae +DA1.1 +DS2.0 +# Caution: be sure you have built zlib with the same CFLAGS. +CCFLAGS=-I$(ZLIBINC) -O -Ae +DA1.1 +DS2.0 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) +z -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-Ae +DA1.1 +DS2.0\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.ibmc b/extern/libpng/include/scripts/makefile.ibmc new file mode 100644 index 0000000000..209d513b1c --- /dev/null +++ b/extern/libpng/include/scripts/makefile.ibmc @@ -0,0 +1,82 @@ +# Makefile for libpng (static) +# IBM C version 3.x for Win32 and OS/2 +# Copyright (C) 2006 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Notes: +# Derived from makefile.std +# All modules are compiled in C mode +# Tested under Win32, expected to work under OS/2 +# Can be easily adapted for IBM VisualAge/C++ for AIX + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = icc +LD = ilink +AR = ilib +RM = del + +CFLAGS = -I$(ZLIBINC) -Mc -O2 -W3 +LDFLAGS = + +# File extensions +O=.obj +A=.lib +E=.exe + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +LIBS = libpng$(A) $(ZLIBLIB)/zlib$(A) + +# Targets +all: libpng$(A) pngtest$(E) + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng$(A): $(OBJS) + $(AR) -out:$@ $(OBJS) + +test: pngtest$(E) + pngtest$(E) + +pngtest: pngtest$(E) + +pngtest$(E): pngtest$(O) libpng$(A) + $(LD) $(LDFLAGS) pngtest$(O) $(LIBS) + +clean: + $(RM) *$(O) + $(RM) libpng$(A) + $(RM) pnglibconf.h + $(RM) pngtest$(E) + $(RM) pngout.png + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.intel b/extern/libpng/include/scripts/makefile.intel new file mode 100644 index 0000000000..1cb9ef3749 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.intel @@ -0,0 +1,110 @@ +# Makefile for libpng +# Microsoft Visual C++ with Intel C/C++ Compiler 4.0 and later + +# Copyright (C) 2006 Glenn Randers-Pehrson +# Copyright (C) 2000, Pawel Mrochen, based on makefile.msc which is +# copyright 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# To use, do "nmake /f scripts\makefile.intel" +# +# ------------------- Intel C/C++ Compiler 4.0 and later ------------------- + +# Where the zlib library and include files are located +ZLIBLIB=..\zlib +ZLIBINC=..\zlib + +# Target CPU +CPU=6 # Pentium II +#CPU=5 # Pentium + +# Calling convention +CALLING=r # __fastcall +#CALLING=z # __stdcall +#CALLING=d # __cdecl + +# Uncomment next to put error messages in a file +#ERRFILE=>>pngerrs + +# -------------------------------------------------------------------------- + +CC=icl -c +CFLAGS=-O2 -G$(CPU)$(CALLING) -Qip -Qunroll4 -I$(ZLIBINC) -nologo +LD=link +LDFLAGS=/SUBSYSTEM:CONSOLE /NOLOGO + +O=.obj + +OBJS=png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) \ +pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) \ +pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + +all: test + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS) + if exist libpng.lib del libpng.lib + lib /NOLOGO /OUT:libpng.lib $(OBJS) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) /OUT:pngtest.exe pngtest.obj libpng.lib $(ZLIBLIB)\zlib.lib + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +test: pngtest.exe + pngtest.exe + + +# End of makefile for libpng diff --git a/extern/libpng/include/scripts/makefile.knr b/extern/libpng/include/scripts/makefile.knr new file mode 100644 index 0000000000..18a39f5375 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.knr @@ -0,0 +1,109 @@ +# makefile for libpng +# Copyright (C) 2002, 2006, 2009 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# This makefile requires the file ansi2knr.c, which you can get +# from the Ghostscript ftp site at ftp://ftp.cs.wisc.edu/ghost/ +# If you have libjpeg, you probably already have ansi2knr.c in the jpeg +# source distribution. + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +CC=cc +CFLAGS=-I../zlib -O +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm +# flags for ansi2knr +ANSI2KNRFLAGS= + +RANLIB=ranlib +#RANLIB=echo + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: ansi2knr libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +# general rule to allow ansi2knr to work +.c.o: + ./ansi2knr $*.c T$*.c + $(CC) $(CFLAGS) -c T$*.c + rm -f T$*.c $*.o + mv T$*.o $*.o + +ansi2knr: ansi2knr.c + $(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr ansi2knr.c + +libpng.a: ansi2knr $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a png.h pngconf.h pnglibconf.h + -@mkdir $(DESTDIR)$(INCPATH) + -@mkdir $(DESTDIR)$(INCPATH)/libpng + -@mkdir $(DESTDIR)$(LIBPATH) + -@rm -f $(DESTDIR)$(INCPATH)/png.h + -@rm -f $(DESTDIR)$(INCPATH)/pngconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + rm -f *.o libpng.a pngtest pngout.png ansi2knr pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.linux b/extern/libpng/include/scripts/makefile.linux new file mode 100644 index 0000000000..59296562b6 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.linux @@ -0,0 +1,239 @@ +# makefile for libpng.a and libpng15.so on Linux ELF with gcc +# Copyright (C) 1998, 1999, 2002, 2006, 2008, 2010-2011 Greg Roelofs and +# Glenn Randers-Pehrson +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 +RELEASE = 2 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng15.a, libpng15.so*, +# libpng15/png.h, libpng15/pngconf.h, and libpng15/pnglibconf.h +# Prefix must be a full pathname. +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located. +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 + +LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS_A=-L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) libpng.a -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest pngtest-static libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-Wl,-rpath,$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -shared -Wl,-soname,$(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +pngtest-static: pngtest.o libpng.a + $(CC) -o pngtest-static $(CFLAGS) pngtest.o $(LDFLAGS_A) + +test: pngtest pngtest-static + @echo "" + @echo " Running pngtest dynamically linked with $(LIBSO):" + @echo "" + ./pngtest + @echo "" + @echo " Running pngtest statically linked with libpng.a:" + @echo "" + ./pngtest-static + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl, -rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h diff --git a/extern/libpng/include/scripts/makefile.mips b/extern/libpng/include/scripts/makefile.mips new file mode 100644 index 0000000000..179d3850b6 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.mips @@ -0,0 +1,94 @@ +# makefile for libpng +# Copyright (C) Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +CC=cc +CFLAGS=-I../zlib -O -systype sysv -DSYSV -w -Dmips +#CFLAGS=-O +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm + +#RANLIB=ranlib +RANLIB=echo + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a + -@mkdir $(DESTDIR)$(INCPATH) + -@mkdir $(DESTDIR)$(INCPATH)/libpng + -@mkdir $(DESTDIR)$(LIBPATH) + -@rm -f $(DESTDIR)$(INCPATH)/png.h + -@rm -f $(DESTDIR)$(INCPATH)/pngconf.h + -@rm -f $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + rm -f *.o libpng.a pngtest pngout.png pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.msc b/extern/libpng/include/scripts/makefile.msc new file mode 100644 index 0000000000..baa863dad9 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.msc @@ -0,0 +1,95 @@ +# makefile for libpng +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# Copyright (C) 2006, 2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Assumes that zlib.lib, zconf.h, and zlib.h have been copied to ..\zlib + +# -------- Microsoft C 5.1 and later, does not use assembler code -------- +MODEL=L +CFLAGS=-Oait -Gs -nologo -W3 -A$(MODEL) -I..\zlib +#-Ox generates bad code with MSC 5.1 +CC=cl +LD=link +LDFLAGS=/e/st:0x1500/noe +O=.obj + +#uncomment next to put error messages in a file +ERRFILE= >> pngerrs + +# variables +OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + +all: libpng.lib + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3) + del libpng.lib + lib libpng $(OBJS1); + lib libpng $(OBJS2); + lib libpng $(OBJS3); + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) pngtest.obj,,,libpng.lib ..\zlib\zlib.lib ; + +test: pngtest.exe + pngtest + +# End of makefile for libpng + diff --git a/extern/libpng/include/scripts/makefile.ne12bsd b/extern/libpng/include/scripts/makefile.ne12bsd new file mode 100644 index 0000000000..1db9cf9511 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.ne12bsd @@ -0,0 +1,50 @@ +# makefile for libpng for NetBSD for the standard +# make obj && make depend && make && make test +# make includes && make install +# Copyright (C) 2002 Patrick R.L. Welche +# Copyright (C) 2007, 2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# You should also run makefile.netbsd + +LOCALBASE?=/usr/local +LIBDIR= ${LOCALBASE}/lib +MANDIR= ${LOCALBASE}/man +INCSDIR=${LOCALBASE}/include/libpng15 + +LIB= png15 +SHLIB_MAJOR= 0 +SHLIB_MINOR= 1.5.2 +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c +INCS= png.h pngconf.h pnglibconf.h +MAN= libpng.3 libpngpf.3 png.5 + +CPPFLAGS+=-I${.CURDIR} + +# We should be able to do something like this instead of the manual +# uncommenting, but it core dumps for me at the moment: +# .if ${MACHINE_ARCH} == "i386" +# MKLINT= no +# .endif + +CLEANFILES+=pngtest.o pngtest pnglibconf.h + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} -c ${CPPFLAGS} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o libpng.a + ${CC} ${LDFLAGS} ${.ALLSRC} -o${.TARGET} -lz -lm + +test: pngtest + cd ${.CURDIR} && ${.OBJDIR}/pngtest + +.include diff --git a/extern/libpng/include/scripts/makefile.netbsd b/extern/libpng/include/scripts/makefile.netbsd new file mode 100644 index 0000000000..8a1fa967ea --- /dev/null +++ b/extern/libpng/include/scripts/makefile.netbsd @@ -0,0 +1,50 @@ +# makefile for libpng for NetBSD for the standard +# make obj && make depend && make && make test +# make includes && make install +# Copyright (C) 2002 Patrick R.L. Welche +# Copyright (C) 2007-2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# You should also run makefile.ne15bsd + +LOCALBASE?=/usr/local +LIBDIR= ${LOCALBASE}/lib +MANDIR= ${LOCALBASE}/man +INCSDIR=${LOCALBASE}/include + +LIB= png +SHLIB_MAJOR= 15 +SHLIB_MINOR= 1.5.2 +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c +INCS= png.h pngconf.h pnglibconf.h +MAN= libpng.3 libpngpf.3 png.5 + +CPPFLAGS+=-I${.CURDIR} + +# We should be able to do something like this instead of the manual +# uncommenting, but it core dumps for me at the moment: +# .if ${MACHINE_ARCH} == "i386" +# MKLINT= no +# .endif + +CLEANFILES+=pngtest.o pngtest pnglibconf.h + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} -c ${CPPFLAGS} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o libpng.a + ${CC} ${LDFLAGS} ${.ALLSRC} -o${.TARGET} -lz -lm + +test: pngtest + cd ${.CURDIR} && ${.OBJDIR}/pngtest + +.include diff --git a/extern/libpng/include/scripts/makefile.openbsd b/extern/libpng/include/scripts/makefile.openbsd new file mode 100644 index 0000000000..4ec9d2f5a6 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.openbsd @@ -0,0 +1,82 @@ +# makefile for libpng +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# Copyright (C) 2007-2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +PREFIX?= /usr/local +LIBDIR= ${PREFIX}/lib +MANDIR= ${PREFIX}/man/cat + +SHLIB_MAJOR= 15 +SHLIB_MINOR= 1.5.2 + +LIB= png +SRCS= png.c pngerror.c pngget.c pngmem.c pngpread.c \ + pngread.c pngrio.c pngrtran.c pngrutil.c pngset.c pngtrans.c \ + pngwio.c pngwrite.c pngwtran.c pngwutil.c + +HDRS= png.h pngconf.h pnglibconf.h + +CFLAGS+= -W -Wall +CPPFLAGS+= -I${.CURDIR} + +NOPROFILE= Yes + +CLEANFILES+= pngtest.o pngtest pnglibconf.h + +MAN= libpng.3 libpngpf.3 png.5 +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO \ + libpng-manual.txt + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} ${CPPFLAGS} ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o + ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} -L${.OBJDIR} -lpng -lz -lm + +test: pngtest + cd ${.OBJDIR} && env \ + LD_LIBRARY_PATH="${.OBJDIR}" ${.OBJDIR}/pngtest + +beforeinstall: + if [ ! -d ${DESTDIR}${PREFIX}/include/libpng ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${PREFIX}/include; \ + fi + if [ ! -d ${DESTDIR}${LIBDIR} ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${LIBDIR}; \ + fi + if [ ! -d ${DESTDIR}${LIBDIR}/debug ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${LIBDIR}/debug; \ + fi + if [ ! -d ${DESTDIR}${MANDIR}3 ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${MANDIR}3; \ + fi + if [ ! -d ${DESTDIR}${MANDIR}5 ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${MANDIR}5; \ + fi + if [ ! -d ${DESTDIR}${PREFIX}/share/doc/png ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${PREFIX}/share/doc/png; \ + fi + +afterinstall: + @rm -f ${DESTDIR}${LIBDIR}/libpng_pic.a + @rm -f ${DESTDIR}${LIBDIR}/debug/libpng.a + @rm -f ${DESTDIR}${PREFIX}/include/png.h + @rm -f ${DESTDIR}${PREFIX}/include/pngconf.h + @rm -f ${DESTDIR}${PREFIX}/include/pnglibconf.h + @rmdir ${DESTDIR}${LIBDIR}/debug 2>/dev/null || true + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${HDRS} ${DESTDIR}${PREFIX}/include + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${HDRS} ${DESTDIR}${PREFIX}/include + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${DOCS} ${DESTDIR}${PREFIX}/share/doc/png + +.include diff --git a/extern/libpng/include/scripts/makefile.sco b/extern/libpng/include/scripts/makefile.sco new file mode 100644 index 0000000000..0aad789a98 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.sco @@ -0,0 +1,218 @@ +# makefile for SCO OSr5 ELF and Unixware 7 with Native cc +# Contributed by Mike Hopkirk (hops@sco.com) modified from Makefile.lnx +# force ELF build dynamic linking, SONAME setting in lib and RPATH in app +# Copyright (C) 2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# where make install puts libpng.a, $(OLDSO)*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CFLAGS= -dy -belf -I$(ZLIBINC) -O3 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-belf\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -G -Wl,-h,$(LIBSOMAJ) -o $(LIBSOMAJ) \ + $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + LD_RUN_PATH=.:$(ZLIBLIB) $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + -@$(RM_F) $(DI)/png.h + -@$(RM_F) $(DI)/pngconf.h + -@$(RM_F) $(DI)/pnglibconf.h + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + pnglibconf.h libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.sggcc b/extern/libpng/include/scripts/makefile.sggcc new file mode 100644 index 0000000000..1611638ba6 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.sggcc @@ -0,0 +1,228 @@ +# makefile for libpng.a and libpng15.so, SGI IRIX with 'cc' +# Copyright (C) 2001-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so, and libpng15/png.h +# Prefix must be a full pathname. + +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib32 +#ZLIBINC=/usr/local/include +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# ABI can be blank to use default for your system, -32, -o32, -n32, or -64 +# See "man abi". zlib must be built with the same ABI. +ABI= + +WARNMORE= # -g -DPNG_DEBUG=5 +CFLAGS=$(ABI) -I$(ZLIBINC) -O $(WARNMORE) -fPIC -mabi=n32 +LDFLAGS=$(ABI) -L. -L$(ZLIBLIB) -lpng -lz -lm +LDSHARED=cc $(ABI) -shared -soname $(LIBSOMAJ) \ + -set_version sgi$(PNGMAJ).0 +# See "man dso" for info about shared objects + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +#LIBPATH=$(exec_prefix)/lib32 +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest shared libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +shared: $(LIBSOMAJ) + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"$(ABI)\"; \ + echo cppflags=\"\"; \ + echo ldopts=\"$(ABI)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + $(RM_F) $(LIBSO) $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + echo + echo Testing local static library. + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):`$(BINPATH)/$(LIBNAME)-config --libdir` \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) libpng.a pngtest pngtesti pngout.png libpng.pc \ + so_locations libpng-config $(LIBSO) $(LIBSOMAJ)* pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.sgi b/extern/libpng/include/scripts/makefile.sgi new file mode 100644 index 0000000000..83db59f817 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.sgi @@ -0,0 +1,229 @@ +# makefile for libpng.a and libpng15.so, SGI IRIX with 'cc' +# Copyright (C) 2001-2002, 2006, 2007, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so, and libpng15/png.h +# Prefix must be a full pathname. + +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib32 +#ZLIBINC=/usr/local/include +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# ABI can be blank to use default for your system, -32, -o32, -n32, or -64 +# See "man abi". zlib must be built with the same ABI. +ABI= + +WARNMORE=-fullwarn +# Note: -KPIC is the default anyhow +#CFLAGS= $(ABI) -I$(ZLIBINC) -O $(WARNMORE) -KPIC # -g -DPNG_DEBUG=5 +CFLAGS=$(ABI) -I$(ZLIBINC) -O $(WARNMORE) +LDFLAGS_A=$(ABI) -L. -L$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS=$(ABI) -L. -L$(ZLIBLIB) -lpng -lz -lm +LDSHARED=cc $(ABI) -shared -soname $(LIBSOMAJ) \ + -set_version sgi$(PNGMAJ).0 +# See "man dso" for info about shared objects + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +#LIBPATH=$(exec_prefix)/lib32 +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest shared libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"$(ABI)\"; \ + echo ldopts=\"$(ABI)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + $(RM_F) $(LIBSO) $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + echo + echo Testing local static library. + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):`$(BINPATH)/$(LIBNAME)-config --libdir` \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png libpng.pc libpng-config \ + $(LIBSO) $(LIBSOMAJ)* \ + so_locations pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.so9 b/extern/libpng/include/scripts/makefile.so9 new file mode 100644 index 0000000000..615c2e3458 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.so9 @@ -0,0 +1,239 @@ +# makefile for libpng on Solaris 9 (beta) with Forte cc +# Updated by Chad Schrock for Solaris 9 +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 2002, 2006, 2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998-2001 Greg Roelofs +# Copyright (C) 1996-1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +PNGMAJ = 15 +LIBNAME = libpng15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +# gcc 2.95 doesn't work. +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, $(OLDSO)*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +#Use the preinstalled zlib that comes with Solaris 9: +ZLIBLIB=/usr/lib +ZLIBINC=/usr/include + +#WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +#CFLAGS=-I$(ZLIBINC) -W -Wall -O3 $(WARNMORE) -g -DPNG_DEBUG=5 -DPNG_NO_MMX_CODE +CFLAGS=-I$(ZLIBINC) -O3 -DPNG_NO_MMX_CODE +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.solaris b/extern/libpng/include/scripts/makefile.solaris new file mode 100644 index 0000000000..24bd61033c --- /dev/null +++ b/extern/libpng/include/scripts/makefile.solaris @@ -0,0 +1,236 @@ +# makefile for libpng on Solaris 2.x with gcc +# Copyright (C) 2004, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) -W -Wall -O \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo cppflags=\"\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.solaris-x86 b/extern/libpng/include/scripts/makefile.solaris-x86 new file mode 100644 index 0000000000..76467622a8 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.solaris-x86 @@ -0,0 +1,236 @@ +# makefile for libpng on Solaris 2.x with gcc +# Copyright (C) 2004, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) -W -Wall -O \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo cppflags=\""; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.std b/extern/libpng/include/scripts/makefile.std new file mode 100644 index 0000000000..30e1646436 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.std @@ -0,0 +1,123 @@ +# makefile for libpng +# Copyright (C) 2002, 2006 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir +LN_SF=ln -sf +RANLIB=ranlib +RM_F=rm -f +AWK = awk +SED = sed +CPP = $(CC) -E +ECHO = echo + +DFNFLAGS = # DFNFLAGS contains -D options to use in the libpng build +CFLAGS=-I$(ZLIBINC) -O # -g -DPNG_DEBUG=5 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# The standard pnglibconf.h exists as scripts/pnglibconf.h.prebuilt, +# copy this if the following doesn't work. +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + $(RM_F) $@ dfn?.out + $(AWK) -f scripts/options.awk out=dfn1.out\ + scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f scripts/options.awk out=dfn2.out dfn1.out 1>&2 + cp dfn2.out $@ + $(RM_F) dfn?.out + +pnglibconf.h: pnglibconf.dfn + $(RM_F) $@ dfn.c dfn?.out + $(ECHO) '#include "pnglibconf.dfn"' >dfn.c + $(CPP) $(DFNFLAGS) dfn.c >dfn1.out + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + dfn1.out >dfn2.out + $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + cp dfn3.out $@ + $(RM_F) dfn.c dfn?.out + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a pnglibconf.h + -@$(MKDIR_P) $(DESTDIR)$(INCPATH) + -@$(MKDIR_P) $(DESTDIR)$(INCPATH)/libpng + -@$(MKDIR_P) $(DESTDIR)$(LIBPATH) + -@$(RM_F) $(DESTDIR)$(INCPATH)/png.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pngconf.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.* dfn.c dfn?.out + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.sunos b/extern/libpng/include/scripts/makefile.sunos new file mode 100644 index 0000000000..383954987e --- /dev/null +++ b/extern/libpng/include/scripts/makefile.sunos @@ -0,0 +1,107 @@ +# makefile for libpng +# Copyright (C) 2002, 2006 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow -Wconversion \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes + +CC=gcc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=ranlib +RM_F=/bin/rm -f + +CFLAGS=-I$(ZLIBINC) -O # $(WARNMORE) -DPNG_DEBUG=5 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a + -@$(MKDIR_P) $(DESTDIR)$(INCPATH) + -@$(MKDIR_P) $(DESTDIR)$(INCPATH)/libpng + -@$(MKDIR_P) $(DESTDIR)$(LIBPATH) + -@$(RM_F) $(DESTDIR)$(INCPATH)/png.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pngconf.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); $(LN_SF) libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/extern/libpng/include/scripts/makefile.tc3 b/extern/libpng/include/scripts/makefile.tc3 new file mode 100644 index 0000000000..462c47fece --- /dev/null +++ b/extern/libpng/include/scripts/makefile.tc3 @@ -0,0 +1,93 @@ +# Makefile for libpng +# TurboC/C++ (Note: All modules are compiled in C mode) + +# To use, do "make -fmakefile.tc3" + +# ----- Turbo C 3.00 (can be modified to work with earlier versions) ----- + +MODEL=l +CFLAGS=-O2 -Z -m$(MODEL) -I..\zlib +#CFLAGS=-D_NO_PROTO -O2 -Z -m$(MODEL) -I..\zlib # Turbo C older than 3.00 +CC=tcc +LD=tcc +LIB=tlib +LDFLAGS=-m$(MODEL) -L..\zlib +O=.obj +E=.exe + +# variables +OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) +OBJSL1 = +png$(O) +pngset$(O) +pngget$(O) +pngrutil$(O) +pngtrans$(O) +OBJSL2 = +pngwutil$(O) +pngmem$(O) +pngpread$(O) +pngread$(O) +pngerror$(O) +OBJSL3 = +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) +pngrio$(O) +pngwio$(O) + +all: libpng$(MODEL).lib pngtest$(E) + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest: pngtest$(E) + +test: pngtest$(E) + pngtest$(E) + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +libpng$(MODEL).lib: $(OBJS1) $(OBJS2) $(OBJS3) + $(LIB) libpng$(MODEL) +$(OBJSL1) + $(LIB) libpng$(MODEL) +$(OBJSL2) + $(LIB) libpng$(MODEL) +$(OBJSL3) + +pngtest$(E): pngtest$(O) libpng$(MODEL).lib + $(LD) $(LDFLAGS) pngtest.obj libpng$(MODEL).lib zlib_$(MODEL).lib + +# End of makefile for libpng diff --git a/extern/libpng/include/scripts/makefile.vcwin32 b/extern/libpng/include/scripts/makefile.vcwin32 new file mode 100644 index 0000000000..6bfeac03f7 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.vcwin32 @@ -0,0 +1,108 @@ +# makefile for libpng +# Copyright (C) 1998 Tim Wegner +# Copyright (C) 2006,2009,2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Assumes that zlib.lib, zconf.h, and zlib.h have been copied to ..\zlib +# To use, do "nmake /f scripts\makefile.vcwin32" + +# -------- Microsoft Visual C++ 2.0 and later, no assembler code -------- + +# Compiler, linker, librarian, and other tools +CC = cl +LD = link +AR = lib +CFLAGS = -nologo -D_CRT_SECURE_NO_DEPRECATE -MD -O2 -W3 -I..\zlib +LDFLAGS = -nologo +ARFLAGS = -nologo +RM = del + +# File extensions +O=.obj + +#uncomment next to put error messages in a file +#ERRFILE= >> pngerrs.log + +# Variables +OBJS1 = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) +OBJS2 = pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) +OBJS3 = pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) + +# Targets +all: libpng.lib + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts\pnglibconf.h.prebuilt + copy scripts\pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS) + -$(RM) $@ + $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(ERRFILE) + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtest.exe: pngtest$(O) libpng.lib + $(LD) $(LDFLAGS) -out:$@ pngtest$(O) libpng.lib ..\zlib\zlib.lib $(ERRFILE) + +test: pngtest.exe + pngtest + +clean: + -$(RM) *$(O) + -$(RM) libpng.lib + -$(RM) pnglibconf.h + -$(RM) pngtest.exe + -$(RM) pngout.png + +# End of makefile for libpng + diff --git a/extern/libpng/include/scripts/makefile.watcom b/extern/libpng/include/scripts/makefile.watcom new file mode 100644 index 0000000000..983b4e3091 --- /dev/null +++ b/extern/libpng/include/scripts/makefile.watcom @@ -0,0 +1,122 @@ +# Makefile for libpng +# Watcom C/C++ 10.0 and later, 32-bit protected mode, flat memory model + +# Copyright (C) 2000, Pawel Mrochen, based on makefile.msc which is +# copyright 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# To use, do "wmake /f scripts\makefile.watcom" + + +# ---------------------- Watcom C/C++ 10.0 and later ----------------------- + +# Where the zlib library and include files are located +ZLIBLIB=..\zlib +ZLIBINC=..\zlib + +# Target OS +OS=DOS +#OS=NT + +# Target CPU +CPU=6 # Pentium Pro +#CPU=5 # Pentium + +# Calling convention +CALLING=r # registers +#CALLING=s # stack + +# Uncomment next to put error messages in a file +#ERRFILE=>>pngerrs + +# -------------------------------------------------------------------------- + + +CC=wcc386 +CFLAGS=-$(CPU)$(CALLING) -fp$(CPU) -fpi87 -oneatx -mf -bt=$(OS) -i=$(ZLIBINC) -zq +LD=wcl386 +LDFLAGS=-zq + +O=.obj + +OBJS1=png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2=pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3=pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + + +all: test + +# see scripts/pnglibconf.mak for more options +# to support watcom calling conventions it is necessary to set PNG_API_RULE to 2 +# in pnglibconf.h - copy scripts/pnglibconf.h.prebuilt, delete the first line and change +# the definition of PNG_API_RULE from 0 to 2. +# +# If you know how to do this with the Watcom build system please supply a patch +# for this makefile to the PNG implementation list. +pnglibconf.h: scripts/pnglibconf.h.prebuilt + @echo please copy scripts/pnglibconf.h.prebuilt and change PNG_API_RULE to 2 + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3) + wlib -b -c -n -q libpng.lib $(OBJS1) + wlib -b -c -q libpng.lib $(OBJS2) + wlib -b -c -q libpng.lib $(OBJS3) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) pngtest.obj libpng.lib $(ZLIBLIB)\zlib.lib + +test: pngtest.exe .symbolic + pngtest.exe + + +# End of makefile for libpng diff --git a/extern/libpng/include/scripts/makevms.com b/extern/libpng/include/scripts/makevms.com new file mode 100644 index 0000000000..f6c326103c --- /dev/null +++ b/extern/libpng/include/scripts/makevms.com @@ -0,0 +1,142 @@ +$! make libpng under VMS +$! +$! +$! Check for MMK/MMS +$! +$! This procedure accepts one parameter (contrib), which causes it to build +$! the programs from the contrib directory instead of libpng. +$! +$ p1 = f$edit(p1,"UPCASE") +$ if p1 .eqs. "CONTRIB" +$ then +$ set def [.contrib.gregbook] +$ @makevms +$ set def [-.pngminus] +$ @makevms +$ set def [--] +$ exit +$ endif +$ Make = "" +$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" +$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" +$! +$! Look for the compiler used +$! +$ zlibsrc = "[-.zlib]" +$ ccopt="/include=''zlibsrc'" +$ if f$getsyi("HW_MODEL").ge.1024 +$ then +$ ccopt = "/prefix=all"+ccopt +$ comp = "__decc__=1" +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ else +$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" +$ then +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs."" +$ then +$ comp = "__gcc__=1" +$ CC :== GCC +$ else +$ comp = "__vaxc__=1" +$ endif +$ else +$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include: +$ ccopt = "/decc/prefix=all"+ccopt +$ comp = "__decc__=1" +$ endif +$ endif +$! +$! Build the thing plain or with mms/mmk +$! +$ write sys$output "Compiling Libpng sources ..." +$ if make.eqs."" +$ then +$ dele pngtest.obj;* +$ CALL MAKE png.OBJ "cc ''CCOPT' png" - + png.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngset.OBJ "cc ''CCOPT' pngset" - + pngset.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngget.OBJ "cc ''CCOPT' pngget" - + pngget.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngread.OBJ "cc ''CCOPT' pngread" - + pngread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" - + pngpread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrtran.OBJ "cc ''CCOPT' pngrtran" - + pngrtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrutil.OBJ "cc ''CCOPT' pngrutil" - + pngrutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngerror.OBJ "cc ''CCOPT' pngerror" - + pngerror.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngmem.OBJ "cc ''CCOPT' pngmem" - + pngmem.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrio.OBJ "cc ''CCOPT' pngrio" - + pngrio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwio.OBJ "cc ''CCOPT' pngwio" - + pngwio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngtrans.OBJ "cc ''CCOPT' pngtrans" - + pngtrans.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwrite.OBJ "cc ''CCOPT' pngwrite" - + pngwrite.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwtran.OBJ "cc ''CCOPT' pngwtran" - + pngwtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwutil.OBJ "cc ''CCOPT' pngwutil" - + pngwutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ write sys$output "Building Libpng ..." +$ CALL MAKE libpng.OLB "lib/crea libpng.olb *.obj" *.OBJ +$ write sys$output "Building pngtest..." +$ CALL MAKE pngtest.OBJ "cc ''CCOPT' pngtest" - + pngtest.c png.h pngconf.h pnglibconf.h +$ call make pngtest.exe - + "LINK pngtest,libpng.olb/lib,''zlibsrc'libz.olb/lib" - + pngtest.obj libpng.olb +$ write sys$output "Testing Libpng..." +$ run pngtest +$ else +$ if f$search("DESCRIP.MMS") .eqs. "" then copy/nolog [.SCRIPTS]DESCRIP.MMS [] +$ 'make'/macro=('comp',zlibsrc='zlibsrc') +$ endif +$ write sys$output "Libpng build completed" +$ exit +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE diff --git a/extern/libpng/include/scripts/options.awk b/extern/libpng/include/scripts/options.awk new file mode 100755 index 0000000000..96c600eab0 --- /dev/null +++ b/extern/libpng/include/scripts/options.awk @@ -0,0 +1,734 @@ +#!/bin/awk -f +# scripts/options.awk - library build configuration control +# +# last changed in libpng version 1.5.0 - January 6, 2011 +# +# Copyright (c) 1998-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# The output of this script is written to the file given by +# the variable 'out'. The script is run twice, once with +# an intermediate output file, 'options.tmp' then again on +# that file to produce the final output: +# +# awk -f scripts/options.awk out=options.tmp scripts/options.dfa 1>&2 +# awk -f scripts/options.awk out=options.dfn options.tmp 1>&2 +# +# Some options may be specified on the command line: +# +# deb=1 Causes debugging to be output +# logunsupported=1 Causes all options to be recorded in the output +# everything=off Causes all options to be disabled by default +# everything=on Causes all options to be enabled by default +# +# If awk fails on your platform, try nawk instead. +# +# These options may also be specified in the original input file (and +# are copied to the preprocessed file). + +BEGIN{ + out="/dev/null" # intermediate, preprocessed, file + pre=-1 # preprocess (first line) + err=0 # in-line exit sets this + start="PNG_DEFN_MAGIC-" # Arbitrary start + end="-PNG_DEFN_END" # Arbitrary end + cx= "/@@@*" # Open C comment for output file + comment=start cx # Comment start + cend="*/" end # Comment end + def=start "#define PNG_@@@" # Arbitrary define + sup="@@@_SUPPORTED" end # end supported option + und=comment "#undef PNG_@@@" # Unsupported option + une="@@@_SUPPORTED" cend # end unsupported option + error=start "ERROR:" # error message + + # Variables + deb=0 # debug - set on command line + everything="" # do not override defaults + logunsupported=0 # write unsupported options too + + # Precreate arrays + option[""] = "" # list of all options: default enabled/disabled + done[""] = 1 # marks option as having been output + requires[""] = "" # requires by option + iffs[""] = "" # if by option + enabledby[""] = "" # options that enable it by option + setting[""] = "" # requires by setting + defaults[""] = "" # used for a defaulted value + doneset[""] = 1 # marks setting as having been output + r[""] = "" # Temporary array + + # For decorating the output file + protect = "" +} + +# The output file must be specified before any input: +out == "/dev/null" { + print "out=output.file must be given on the command line" + err = 1 + exit 1 +} + +# The very first line indicates whether we are reading pre-processed +# input or not, this must come *first* because 'PREPROCESSED' needs +# to be the very first line in the temporary file. +pre == -1{ + if ($0 == "PREPROCESSED") { + pre = 0 + next + } else { + pre = 1 + print "PREPROCESSED" >out + # And fall through to continue processing + } +} + +# variable=value +# Sets the given variable to the given value (the syntax is fairly +# free form, except for deb (you are expected to understand how to +# set the debug variable...) +# +# This happens before the check on 'pre' below skips most of the +# rest of the actions, so the variable settings happen during +# preprocessing but are recorded in the END action too. This +# allows them to be set on the command line too. +$0 ~ /^[ ]*everything[ =]*off[ ]*$/{ + everything = "off" + next +} +$0 ~ /^[ ]*everything[ =]*on[ ]*$/{ + everything = "on" + next +} +$0 ~ /^[ ]*logunsupported[ =]*0[ ]*$/{ + logunsupported = 0 + next +} +$0 ~ /^[ ]*logunsupported[ =]*1[ ]*$/{ + logunsupported = 1 + next +} +$1 == "deb" && $2 == "=" && NF == 3{ + deb = $3 + next +} + +# Preprocessing - this just copies the input file with lines +# that need preprocessing (just chunk at present) expanded +# The bare "pre" instead of "pre != 0" crashes under Sunos awk +pre && $1 != "chunk"{ + print >out + next +} + +# The first characters of the line determine how it is processed, +# leading spaces are ignored. In general tokens that are not +# keywords are the names of options. An option 'name' is +# controlled by the definition of the corresponding macros: +# +# PNG_name_SUPPORTED The option is turned on +# PNG_NO_name +# PNG_NO_name_SUPPORTED If the first macro is not defined +# either of these will turn the option off +# +# If none of these macros are defined the option is turned on, unless +# the keyword 'off' is given in a line relating to the option. The +# keyword 'on' can also be given, but it will be ignored (since it is +# the default.) +# +# In the syntax below a 'name' is indicated by "NAME", other macro +# values are indicated by "MACRO", as with "NAME" the leading "PNG_" +# is omitted, but in this case the "NO_" prefix and the "_SUPPORTED" +# suffix are never used. +# +# Each line is introduced by a keyword - the first non-space characters +# on the line. A line starting with a '#' is a comment - it is totally +# ignored. Keywords are as follows, a NAME, is simply a macro name +# without the leading PNG_, PNG_NO_ or the trailing _SUPPORTED. + +$1 ~ /^#/ || $0 ~ /^[ ]*$/{ + next +} + +# com +# The whole line is placed in the output file as a comment with +# the preceding 'com' removed +$1 == "com"{ + if (NF > 1) { + # sub(/^[ ]*com[ ]*/, "") + $1 = "" + print comment, $0, cend >out + } else + print start end >out + next +} + +# file output input protect +# Informational: the official name of the input file (without +# make generated local directories), the official name of the +# output file and, if required, a name to use in a protection +# macro for the contents. +$1 == "file" && NF >= 2{ + print comment, $2, cend >out + print comment, "Machine generated file: DO NOT EDIT", cend >out + if (NF >= 3) + print comment, "Derived from:", $3, cend >out + protect = $4 + if (protect != "") { + print start "#ifndef", protect end >out + print start "#define", protect end >out + } + next +} + +# option NAME ( (requires|enables|if) NAME* | on | off | disabled )* +# Declares an option 'NAME' and describes its default setting (disabled) +# and its relationship to other options. The option is disabled +# unless *all* the options listed after 'requires' are set and at +# least one of the options listed after 'if' is set. If the +# option is set then it turns on all the options listed after 'enables'. +# +# Note that "enables" takes priority over the required/if/disabled/off +# setting of the target option. +# +# The definition file may list an option as 'disabled': off by default, +# otherwise the option is enabled: on by default. A later (and it must +# be later) entry may turn an option on or off explicitly. + +$1 == "option" && NF >= 2{ + onoff = option[$2] # records current (and the default is "", enabled) + key = "" + for (i=3; i<=NF; ++i) { + if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") { + key = "" + if (onoff != $(i)) { + # on or off can zap disabled or enabled: + if (onoff == "" || (onoff == "disabled" || onoff == "enabled") && ($(i) == "on" || $(i) == "off")) { + # It's easy to mis-spell the option when turning it + # on or off, so warn about it here: + if (onoff == "" && ($(i) == "on" || $(i) == "off")) { + print $2 ": ERROR: turning unrecognized option", $(i) + # For the moment error out - it is safer + err = 1 # prevent END{} running + exit 1 + } + onoff = $(i) + } else { + # Print a message, otherwise the error + # below is incomprehensible + print $2 ": currently", onoff ": attempt to turn", $(i) + break + } + } + } else if ($(i) == "requires" || $(i) == "if" || $(i) == "enables") { + key = $(i) + } else if (key == "requires") { + requires[$2] = requires[$2] " " $(i) + } else if (key == "if") { + iffs[$2] = iffs[$2] " " $(i) + } else if (key == "enables") { + enabledby[$(i)] = enabledby[$(i)] " " $2 + } else + break # bad line format + } + + if (i > NF) { + # Set the option, defaulting to 'enabled' + if (onoff == "") onoff = "enabled" + option[$2] = onoff + next + } + # Else fall through to the error handler +} + +# chunk NAME [requires OPT] [on|off|disabled] +# Expands to the 'option' settings appropriate to the reading and +# writing of an ancilliary PNG chunk 'NAME': +# +# option READ_NAME requires READ_ANCILLARY_CHUNKS [READ_OPT] +# option READ_NAME enables NAME +# [option READ_NAME off] +# option WRITE_NAME requires WRITE_ANCILLARY_CHUNKS [WRITE_OPT] +# option WRITE_NAME enables NAME +# [option WRITE_NAME off] + +pre != 0 && $1 == "chunk" && NF >= 2{ + # 'chunk' is handled on the first pass by writing appropriate + # 'option' lines into the intermediate file. + onoff = "" + reqread = "" + reqwrite = "" + i = 3 # indicates format error + if (NF > 2) { + # read the keywords/additional OPTS + req = 0 + for (i=3; i<=NF; ++i) { + if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") { + if (onoff != $(i)) { + if (onoff == "") + onoff = $(i) + else + break # on/off conflict + } + } else if ($(i) == "requires") + req = 1 + else if (req != 1) + break # bad line: handled below + else { + reqread = reqread " READ_" $(i) + reqwrite = reqwrite " WRITE_" $(i) + } + } + } + + if (i > NF) { + # Output new 'option' lines to the intermediate file (out) + print "option READ_" $2, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", $2, onoff >out + print "option WRITE_" $2, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", $2, onoff >out + next + } + # Else hit the error handler below - bad line format! +} + +# setting MACRO ( requires MACRO* )* [ default VALUE ] +# Behaves in a similar way to 'option' without looking for NO_ or +# _SUPPORTED; the macro is enabled if it is defined so long as all +# the 'requires' macros are also defined. The definitions may be +# empty, an error will be issued if the 'requires' macros are +# *not* defined. If given the 'default' value is used if the +# macro is not defined. The default value will be re-tokenised. +# (BTW: this is somewhat restrictive, it mainly exists for the +# support of non-standard configurations and numeric parameters, +# see the uses in scripts/options.dat + +$1 == "setting" && (NF == 2 || NF >= 3 && ($3 == "requires" || $3 == "default")){ + reqs = "" + deflt = "" + isdef = 0 + key = "" + for (i=3; i<=NF; ++i) + if ($(i) == "requires" || $(i) == "default") { + key = $(i) + if (key == "default") isdef = 1 + } else if (key == "requires") + reqs = reqs " " $(i) + else if (key == "default") + deflt = deflt " " $(i) + else + break # Format error, handled below + + setting[$2] = reqs + # NOTE: this overwrites a previous value silently + if (isdef && deflt == "") + deflt = " " # as a flag to force output + defaults[$2] = deflt + next +} + +# The order of the dependency lines (option, chunk, setting) is irrelevant +# - the 'enables', 'requires' and 'if' settings will be used to determine +# the correct order in the output and the final values in pnglibconf.h are +# not order dependent. 'requires' and 'if' entries take precedence over +# 'enables' from other options; if an option requires another option it +# won't be set regardless of any options that enable it unless the other +# option is also enabled. +# +# Similarly 'enables' trumps a NO_ definition in CFLAGS or pngusr.h +# +# For simplicity cycles in the definitions are regarded as errors, +# even if they are not ambiguous. +# A given NAME can be specified in as many 'option' lines as required, the +# definitions are additive. + +# For backwards compatibility equivalent macros may be listed thus: +# +# = [NO_]NAME MACRO +# Makes -DMACRO equivalent to -DPNG_NO_NAME or -DPNG_NAME_SUPPORTED +# as appropriate. +# +# The definition is injected into the C compiler input when encountered +# in the second pass (so all these definitions appear *after* the @ +# lines!) +# +# 'NAME' is as above, but 'MACRO' is the full text of the equivalent +# old, deprecated, macro. + +$1 == "=" && NF == 3{ + print "#ifdef PNG_" $3 >out + if ($2 ~ /^NO_/) + print "# define PNG_" $2 >out + else + print "# define PNG_" $2 "_SUPPORTED" >out + print "#endif" >out + next +} + +# Lines may be injected into the C compiler input by preceding them +# with an "@" character. The line is copied with just the leading +# @ removed. + +$1 ~ /^@/{ + # sub(/^[ ]*@/, "") + $1 = substr($1, 2) + print >out + next +} + +# Check for unreognized lines, because of the preprocessing chunk +# format errors will be detected on the first pass independent of +# any other format errors. +{ + print "options.awk: bad line (" NR "):", $0 + err = 1 # prevent END{} running + exit 1 +} + +# For checking purposes names that start with "ok_" or "fail_" are +# not output to pnglibconf.h and must be either enabled or disabled +# respectively for the build to succeed. This allows interdependencies +# between options of the form "at least one of" or "at most one of" +# to be checked. For example: +# +# option FLOATING_POINT enables ok_math +# option FIXED_POINT enables ok_math +# This ensures that at least one of FLOATING_POINT and FIXED_POINT +# must be set for the build to succeed. +# +# option fail_math requires FLOATING_POINT FIXED_POINT +# This means the build will fail if *both* FLOATING_POINT and +# FIXED_POINT are set (this is an example; in fact both are allowed.) +# +# If all these options were given the build would require exactly one +# of the names to be enabled. + +END{ + # END{} gets run on an exit (a traditional awk feature) + if (err) exit 1 + + if (pre) { + # Record the final value of the variables + print "deb =", deb >out + if (everything != "") { + print "everything =", everything >out + } + print "logunsupported =", logunsupported >out + exit 0 + } + + # Do the 'setting' values first, the algorithm the standard + # tree walk (O(1)) done in an O(2) while/for loop; interations + # settings x depth, outputing the deepest required macros + # first. + print "" >out + print "/* SETTINGS */" >out + print comment, "settings", cend >out + finished = 0 + while (!finished) { + finished = 1 + movement = 0 # done nothing + for (i in setting) if (!doneset[i]) { + nreqs = split(setting[i], r) + if (nreqs > 0) { + for (j=1; j<=nreqs; ++j) if (!doneset[r[j]]) { + break + } + if (j<=nreqs) { + finished = 0 + continue # try a different setting + } + } + + # All the requirements have been processed, output + # this setting. + if (deb) print "setting", i + print "" >out + print "/* setting: ", i >out + print " * requires:" setting[i] >out + print " * default: ", defaults[i], "*/" >out + if (defaults[i] == "") { # no default, only check if defined + print "#ifdef PNG_" i >out + } + for (j=1; j<=nreqs; ++j) { + print "# ifndef PNG_" r[j] >out + print error, i, "requires", r[j] end >out + print "# endif" >out + } + if (defaults[i] != "") { # default handling + print "#ifdef PNG_" i >out + } + print def i, "PNG_" i end >out + if (defaults[i] != "") { + print "#else /*default*/" >out + # And add the default definition for the benefit + # of later settings an options test: + print "# define PNG_" i defaults[i] >out + print def i defaults[i] end >out + } + print "#endif" >out + + doneset[i] = 1 + ++movement + } + + if (!finished && !movement) { + print "setting: loop or missing setting in 'requires', cannot process:" + for (i in setting) if (!doneset[i]) { + print " setting", i, "requires" setting[i] + } + exit 1 + } + } + print comment, "end of settings", cend >out + + # Now do the options - somewhat more complex. The dependency + # tree is thus: + # + # name > name + # name requires name + # name if name + # name enabledby name + # + # First build a list 'tree' by option of all the things on which + # it depends. + print "" >out + print "/* OPTIONS */" >out + print comment, "options", cend >out + for (opt in enabledby) tree[opt] = 1 # may not be explicit options + for (opt in option) if (opt != "") { + o = option[opt] + # option should always be one of the following values + if (o != "on" && o != "off" && o != "disabled" && o != "enabled") { + print "internal option error (" o ")" + exit 1 + } + tree[opt] = "" # so unlisted options marked + } + for (opt in tree) if (opt != "") { + if (tree[opt] == 1) { + tree[opt] = "" + if (option[opt] != "") { + print "internal error (1)" + exit 1 + } + # Macros only listed in 'enables' remain off unless + # one of the enabling macros is on. + option[opt] = "disabled" + } + + split("", list) # clear 'list' + # Now add every requires, iffs or enabledby entry to 'list' + # so that we can add a unique list of requirements to tree[i] + split(requires[opt] iffs[opt] enabledby[opt], r) + for (i in r) list[r[i]] = 1 + for (i in list) tree[opt] = tree[opt] " " i + } + + # print the tree for extreme debugging + if (deb > 2) for (i in tree) if (i != "") print i, "depends-on" tree[i] + + # Ok, now check all options marked explicitly 'on' or 'off': + # + # If an option[opt] is 'on' then turn on all requires[opt] + # If an option[opt] is 'off' then turn off all enabledby[opt] + # + # Error out if we have to turn 'on' an 'off' option or vice versa. + npending = 0 + for (opt in option) if (opt != "") { + if (option[opt] == "on" || option[opt] == "off") { + pending[++npending] = opt + } + } + + err = 0 # set on error + while (npending > 0) { + opt = pending[npending--] + if (option[opt] == "on") { + nreqs = split(requires[opt], r) + for (j=1; j<=nreqs; ++j) { + if (option[r[j]] == "off") { + print "option", opt, "turned on, but requirement", r[j], "is turned off" + err = 1 + } else if (option[r[j]] != "on") { + option[r[j]] = "on" + pending[++npending] = r[j] + } + } + } else { + if (option[opt] != "off") { + print "internal error (2)" + exit 1 + } + nreqs = split(enabledby[opt], r) + for (j=1; j<=nreqs; ++j) { + if (option[r[j]] == "on") { + print "option", opt, "turned off, but enabled by", r[j], "which is turned on" + err = 1 + } else if (option[r[j]] != "off") { + option[r[j]] = "off" + pending[++npending] = r[j] + } + } + } + } + if (err) exit 1 + + # option[i] is now the complete list of all the tokens we may + # need to output, go through it as above, depth first. + finished = 0 + while (!finished) { + finished = 1 + movement = 0 # done nothing + for (i in option) if (!done[i]) { + nreqs = split(tree[i], r) + if (nreqs > 0) { + for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { + break + } + if (j<=nreqs) { + finished = 0 + continue # next option + } + } + + # All the requirements have been processed, output + # this option. An option is _SUPPORTED if: + # + # all 'requires' are _SUPPORTED AND + # at least one of the 'if' options are _SUPPORTED AND + # EITHER: + # The name is _SUPPORTED (on the command line) + # OR: + # an 'enabledby' is _SUPPORTED + # OR: + # NO_name is not defined AND + # the option is not disabled; an option is disabled if: + # option == off + # option == disabled && everything != on + # option == "" && everything == off + if (deb) print "option", i + print "" >out + print "/* option:", i, option[i] >out + print " * requires: " requires[i] >out + print " * if: " iffs[i] >out + print " * enabled-by:" enabledby[i], "*/" >out + print "#undef PNG_on" >out + print "#define PNG_on 1" >out + + # requires + nreqs = split(requires[i], r) + for (j=1; j<=nreqs; ++j) { + print "#ifndef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_on /*!" r[j] "*/" >out + # this error appears in the final output if something + # was switched 'on' but the processing above to force + # the requires did not work + if (option[i] == "on") { + print error, i, "requires", r[j] end >out + } + print "#endif" >out + } + + # if + nreqs = split(iffs[i], r) + print "#undef PNG_no_if" >out + if (nreqs > 0) { + print "/* if" iffs[i], "*/" >out + print "#define PNG_no_if 1" >out + for (j=1; j<=nreqs; ++j) { + print "#ifdef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_no_if /*" r[j] "*/" >out + print "#endif" >out + } + print "#ifdef PNG_no_if /*missing if*/" >out + print "# undef PNG_on" >out + # There is no checking above for this, because we + # don't know which 'if' to choose, so whine about + # it here: + if (option[i] == "on") { + print error, i, "needs one of:", iffs[i] end >out + } + print "#endif" >out + } + + print "#ifdef PNG_on /*requires, if*/" >out + # enables + print "# undef PNG_not_enabled" >out + print "# define PNG_not_enabled 1" >out + print " /* enabled by" enabledby[i], "*/" >out + nreqs = split(enabledby[i], r) + for (j=1; j<=nreqs; ++j) { + print "#ifdef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_not_enabled /*" r[j] "*/" >out + # Oops, probably not intended (should be factored + # out by the checks above). + if (option[i] == "off") { + print error, i, "enabled by:", r[j] end >out + } + print "#endif" >out + } + + print "# ifndef PNG_" i "_SUPPORTED /*!command line*/" >out + print "# ifdef PNG_not_enabled /*!enabled*/" >out + if (option[i] == "off" || option[i] == "disabled" && everything != "on" || option[i] == "enabled" && everything == "off") { + print "# undef PNG_on /*default off*/" >out + } else { + print "# ifdef PNG_NO_" i >out + print "# undef PNG_on /*turned off*/" >out + print "# endif" >out + print "# ifdef PNG_NO_" i "_SUPPORTED" >out + print "# undef PNG_on /*turned off*/" >out + print "# endif" >out + } + print "# endif /*!enabled*/" >out + print "# ifdef PNG_on" >out + # The _SUPPORTED macro must be defined so that dependent + # options output later work. + print "# define PNG_" i "_SUPPORTED" >out + print "# endif" >out + print "# endif /*!command line*/" >out + # If PNG_on is still set the option should be defined in + # pnglibconf.h + print "# ifdef PNG_on" >out + if (i ~ /^fail_/) { + print error, i, "is on: enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out + } else if (i !~ /^ok_/) { + print def i sup >out + } + print "# endif /* definition */" >out + print "#endif /*requires, if*/" >out + if (logunsupported || i ~ /^ok_/) { + print "#ifndef PNG_on" >out + if (logunsupported) { + print und i une >out + } + if (i ~ /^ok_/) { + print error, i, "not enabled: requires:" requires[i] ", enabled by:" iffs[i] enabledby[i] end >out + } + print "#endif" >out + } + + done[i] = 1 + ++movement + } + + if (!finished && !movement) { + print "option: loop or missing option in dependency tree, cannot process:" + for (i in option) if (!done[i]) { + print " option", i, "depends on" tree[i], "needs:" + nreqs = split(tree[i], r) + if (nreqs > 0) for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { + print " " r[j] + } + } + exit 1 + } + } + print comment, "end of options", cend >out + + # Regular end - everything looks ok + if (protect != "") { + print start "#endif", cx, protect, "*/" end >out + } +} diff --git a/extern/libpng/include/scripts/pnglibconf.dfa b/extern/libpng/include/scripts/pnglibconf.dfa new file mode 100644 index 0000000000..26afef866e --- /dev/null +++ b/extern/libpng/include/scripts/pnglibconf.dfa @@ -0,0 +1,550 @@ +# scripts/pnglibconf.dfa - library build configuration control +# +@/*- pnglibconf.dfn intermediate file +@ * generated from scripts/pnglibconf.dfa +@ */ +# +com pnglibconf.h - library build configuration +com +com libpng version 1.5.0 - January 6, 2011 +com +com Copyright (c) 1998-2011 Glenn Randers-Pehrson +com +com This code is released under the libpng license. +com For conditions of distribution and use, see the disclaimer +com and license in png.h +com + +file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H + +# This file is preprocessed by scripts/options.awk and the +# C compiler to generate 'pnglibconf.h' - a list of all the +# configuration options. The file lists the various options +# that can *only* be specified during the libpng build; +# pnglibconf.h freezes the definitons selected for the specific +# build. +# +# The syntax is detailed in scripts/options.awk, this is a summary +# only: +# +# setting [requires ...] [default] +# #define PNG_ /* value comes from current setting */ +# option [requires ...] [if ...] [enables ...] [disabled] +# #define PNG__SUPPORTED if the requirements are met and +# enable the other options listed +# chunk [requires ...] [disabled] +# Enable chunk processing for the given ancillary chunk +# +# Note that the 'on' and 'off' keywords, while valid on both option +# and chunk, should not be used in this file because they force the +# relevant options on or off. + +#---------------------------------------------------------------------- + +# The following setting, option and chunk values can all be changed +# while building libpng: +# +# setting: change 'setting' lines to fine tune library performance, +# changes to the settings don't affect the libpng API functionally +# +# option: change 'option' lines to remove or add capabilities from +# or to the library; options change the library API +# +# chunk: change 'chunk' lines to remove capabilities to process +# optional ('ancillary') chunks. This does not prevent PNG +# decoding but does change the libpng API because some chunks +# will be ignored. +# +# There are three ways of disabling features, in no particular order: +# +# 1) Create 'pngusr.h', enter the required private build information +# detailed below and #define PNG_NO_ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index e8c4745f15..d8d2058138 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -50,7 +50,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + From 80cd64e50df1bbffc4e7e55c775bf83359e98c84 Mon Sep 17 00:00:00 2001 From: Colby Klein Date: Sun, 8 May 2011 17:36:50 -0700 Subject: [PATCH 016/333] Hopefully improve FFMpeg issues on linux (fix #260) --- Utils/build.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Utils/build.sh b/Utils/build.sh index 49f19b0cb1..4f0914be72 100755 --- a/Utils/build.sh +++ b/Utils/build.sh @@ -147,23 +147,23 @@ if [ ! -d $ffmpeg ]; then fi if [ -n "$s_download" ]; then exit 0; fi -args='--disable-shared --enable-static --disable-debug +args='--enable-static --disable-debug --enable-memalign-hack --disable-network --enable-small ---disable-encoders --disable-ffmpeg --disable-ffserver ---disable-ffplay --disable-muxers --enable-demuxer=avi +--disable-encoders --disable-ffserver +--enable-demuxer=avi --enable-demuxer=h261 --enable-demuxer=h263 --enable-demuxer=h264 --enable-demuxer=m4v --enable-demuxer=mjpeg --enable-demuxer=mov --enable-demuxer=mpegps --enable-demuxer=mpegts --enable-demuxer=mpegvideo --enable-demuxer=ogg --enable-demuxer=rawvideo --enable-demuxer=yuv4mpegpipe ---disable-decoders --enable-decoder=h261 --enable-decoder=h263 +--enable-decoder=h261 --enable-decoder=h263 --enable-decoder=h263i --enable-decoder=h264 --enable-decoder=huffyuv --enable-decoder=mjpeg --enable-decoder=mjpegb --enable-decoder=mpeg_xvmc --enable-decoder=mpeg1video --enable-decoder=mpeg2video --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 ---enable-decoder=rawvideo --enable-decoder=theora --disable-parsers +--enable-decoder=rawvideo --enable-decoder=theora --enable-parser=h261 --enable-parser=h263 --enable-parser=h264 --enable-parser=mjpeg --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=mpegvideo @@ -195,7 +195,8 @@ fi if [ -n "$s_stepmania" ]; then exit 0; fi if [ ! -f stepmania -o ! -f GtkModule.so ]; then message 'Copying StepMania binaries' - call cp _build/src/stepmania _build/src/GtkModule.so . + call cp _build/src/stepmania . + #_build/src/GtkModule.so . # we tend to not have this file! fi From 9384f82ccda5c18c462f1d194b2a6dd600e74266 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 9 May 2011 22:37:15 +0700 Subject: [PATCH 017/333] [splittiming] a function to create steps for the song (259 build errors) --- src/NotesLoaderSM.cpp | 2 +- src/Song.cpp | 12 ++++++++++++ src/Song.h | 6 +++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index f1ab8ec5ad..f937bdf78c 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -458,7 +458,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache } out.m_Timing.m_sFile = sPath; - LoadTimingFromSMFile( msd, out.m_Timing ); + LoadTimingFromSMFile( msd, out.m_SongTiming ); for( unsigned i=0; im_Timing = m_SongTiming; +} + void Song::GetDisplayBpms( DisplayBpms &AddTo ) const { if( m_DisplayBPMType == DISPLAY_BPM_SPECIFIED ) diff --git a/src/Song.h b/src/Song.h index 2b6769566f..1d49724795 100644 --- a/src/Song.h +++ b/src/Song.h @@ -336,11 +336,15 @@ public: void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); } BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); } */ + + Steps *CreateSteps(); + void InitSteps(Steps *pSteps); /** * @brief Retrieve the beat based on the specified time. * @param fElapsedTime the amount of time since the Song started. * @return the appropriate beat. */ + /* [splittiming] float SongGetBeatFromElapsedTime( float fElapsedTime ) const { return m_SongTiming.GetBeatFromElapsedTime( fElapsedTime ); @@ -358,7 +362,7 @@ public: { return steps.m_Timing.GetElapsedTimeFromBeat( fBeat ); } - + */ /* [splittiming] float GetBeatFromElapsedTime( float fElapsedTime ) const From 0d42b00621f0ae1e96cd4931ef00ed7eb66e1be2 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 9 May 2011 22:41:49 +0700 Subject: [PATCH 018/333] [splittiming] Fix NotesLoaderDWI, NotesLoaderSM, NotesWriterSWI, NotesWriterSM by replace occurences of m_Timing with m_SongTiming. (224 build errors) --- src/NotesLoaderDWI.cpp | 10 +++++----- src/NotesLoaderSM.cpp | 2 +- src/NotesWriterDWI.cpp | 22 +++++++++++----------- src/NotesWriterSM.cpp | 34 +++++++++++++++++----------------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/NotesLoaderDWI.cpp b/src/NotesLoaderDWI.cpp index b15c74252f..0c0f327e98 100644 --- a/src/NotesLoaderDWI.cpp +++ b/src/NotesLoaderDWI.cpp @@ -481,11 +481,11 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla if( PREFSMAN->m_bQuirksMode ) { - out.AddBPMSegment( BPMSegment(0, fBPM) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(0, fBPM) ); } else{ if( fBPM > 0.0f ) - out.AddBPMSegment( BPMSegment(0, fBPM) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(0, fBPM) ); else LOG->UserLog( "Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.", NoteRowToBeat(0), fBPM ); @@ -517,7 +517,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla else if( 0==stricmp(sValueName,"GAP") ) // the units of GAP is 1/1000 second - out.m_Timing.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f; + out.m_SongTiming.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f; else if( 0==stricmp(sValueName,"SAMPLESTART") ) out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]); @@ -542,7 +542,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla int iFreezeRow = BeatToNoteRow( StringToFloat(arrayFreezeValues[0]) / 4.0f ); float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ) / 1000.0f; - out.AddStopSegment( StopSegment(iFreezeRow, fFreezeSeconds) ); + out.m_SongTiming.AddStopSegment( StopSegment(iFreezeRow, fFreezeSeconds) ); // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds ); } } @@ -567,7 +567,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla if( fBPM > 0.0f ) { BPMSegment bs( iStartIndex, fBPM ); - out.AddBPMSegment( bs ); + out.m_SongTiming.AddBPMSegment( bs ); } else { diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index f937bdf78c..dee9aa1fb9 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -457,7 +457,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache return false; } - out.m_Timing.m_sFile = sPath; + out.m_SongTiming.m_sFile = sPath; LoadTimingFromSMFile( msd, out.m_SongTiming ); for( unsigned i=0; i 1) + if( out.m_SongTiming.m_BPMSegments.size() > 1) { f.Write( "#CHANGEBPM:" ); - for( unsigned i=1; i 0 ) @@ -111,25 +111,25 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.Write( "#BPMS:" ); - for( unsigned i=0; im_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) ); vector::const_iterator iter2 = iter; iter2++; - if( iter2 != out.m_Timing.m_vTimeSignatureSegments.end() ) + if( iter2 != out.m_SongTiming.m_vTimeSignatureSegments.end() ) f.Write( "," ); } f.PutLine( ";" ); - ASSERT( !out.m_Timing.m_TickcountSegments.empty() ); + ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() ); f.Write( "#TICKCOUNTS:" ); - for( unsigned i=0; i Date: Mon, 9 May 2011 22:47:47 +0700 Subject: [PATCH 019/333] [splittiming] replace `new Steps` with `[song].CreateSteps()` (224 build errors) --- src/NotesLoaderBMS.cpp | 2 +- src/NotesLoaderDWI.cpp | 2 +- src/NotesLoaderMidi.cpp | 2 +- src/NotesLoaderPMS.cpp | 2 +- src/NotesLoaderSM.cpp | 4 ++-- src/NotesLoaderSMA.cpp | 4 ++-- src/NotesLoaderSSC.cpp | 6 +++--- src/ScreenEdit.cpp | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index d90a368591..4a95e85d57 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -1031,7 +1031,7 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out ) // Create a Steps for each. vector apSteps; for( unsigned i=0; i &Bla 0==stricmp(sValueName,"COUPLE") || 0==stricmp(sValueName,"SOLO") ) { - Steps* pNewNotes = new Steps; + Steps* pNewNotes = out.CreateSteps(); LoadFromDWITokens( sParams[0], sParams[1], diff --git a/src/NotesLoaderMidi.cpp b/src/NotesLoaderMidi.cpp index 6de736cabe..a74b3610a8 100644 --- a/src/NotesLoaderMidi.cpp +++ b/src/NotesLoaderMidi.cpp @@ -877,7 +877,7 @@ skip_track: } } - Steps *pSteps = new Steps; + Steps *pSteps = songOut.CreateSteps(); pSteps->m_StepsType = StepsType_guitar_five; pSteps->SetDifficulty( (Difficulty)(gd+1) ); pSteps->SetNoteData( noteData ); diff --git a/src/NotesLoaderPMS.cpp b/src/NotesLoaderPMS.cpp index 08f8efbb79..b733aa3d9f 100644 --- a/src/NotesLoaderPMS.cpp +++ b/src/NotesLoaderPMS.cpp @@ -843,7 +843,7 @@ bool PMSLoader::LoadFromDir( const RString &sDir, Song &out ) /* Create a Steps for each. */ vector apSteps; for( unsigned i=0; iCreateSteps(); LoadFromSMTokens( sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6], *pNewNotes); diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index dd6ce2c60f..93dcb65095 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -360,7 +360,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) continue; } - Steps* pNewNotes = new Steps; + Steps* pNewNotes = out.CreateSteps(); LoadFromSMATokens( sParams[1], sParams[2], @@ -702,7 +702,7 @@ bool SMALoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat if( !bAddStepsToSong ) return true; - Steps* pNewNotes = new Steps; + Steps* pNewNotes = pSong->CreateSteps(); LoadFromSMATokens( sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6], *pNewNotes); diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index a2308e9fd2..59483ee25f 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -686,7 +686,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="NOTEDATA" ) { state = GETTING_STEP_INFO; - pNewNotes = new Steps; + pNewNotes = out.CreateSteps(); } break; } @@ -957,7 +957,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat else if( sValueName=="NOTEDATA" ) { - pNewNotes = new Steps; + pNewNotes = pSong->CreateSteps(); bSSCFormat = true; } if( sValueName=="STEPSTYPE" ) @@ -1062,7 +1062,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat } else { - pNewNotes = new Steps; + pNewNotes = pSong->CreateSteps(); SMLoader::LoadFromSMTokens( sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6], *pNewNotes); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 52e9c62ea0..49b057da6d 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3953,7 +3953,7 @@ void ScreenEdit::RevertFromDisk() // put a blank Steps in its place. Note that this does not have to be the // work of someone maliciously changing the simfile; it could happen to // someone editing a new stepchart and reverting from disk, for example. - pNewSteps = new Steps(); + pNewSteps = GAMESTATE->m_pCurSong->CreateSteps(); pNewSteps->CreateBlank( id.GetStepsType() ); pNewSteps->SetDifficulty( id.GetDifficulty() ); GAMESTATE->m_pCurSong->AddSteps( pNewSteps ); From 6162fe519b7ddb6601a067af5e587e81c4e34309 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 9 May 2011 23:00:29 +0700 Subject: [PATCH 020/333] [splittiming] ArrowEffects and ScreenGameplay (222) --- src/ArrowEffects.cpp | 2 +- src/ScreenGameplay.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 7df7a37015..ffb21ae3d8 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -231,7 +231,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) { float fSongSeconds = GAMESTATE->m_fMusicSecondsVisible; - float fNoteSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(fNoteBeat); + float fNoteSeconds = GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; float fBPS = fBPM/60.f; diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 814093883a..1ac4b6d8c5 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1325,7 +1325,7 @@ void ScreenGameplay::StartPlayingSong( float fMinTimeToNotes, float fMinTimeToMu { const float fFirstBeat = GAMESTATE->m_pCurSong->m_fFirstBeat; - const float fFirstSecond = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat( fFirstBeat ); + const float fFirstSecond = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( fFirstBeat ); float fStartDelay = fMinTimeToNotes - fFirstSecond; fStartDelay = max( fStartDelay, fMinTimeToMusic ); p.m_StartSecond = -fStartDelay; From a1bf5d99f78134acf1f36de09e2de3cc90696bb3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 14:23:05 -0400 Subject: [PATCH 021/333] More doxygen catchup. --- src/ScreenEdit.h | 53 ++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index c9bf604ffb..ea10ca22a2 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -128,8 +128,7 @@ enum EditButton EDIT_BUTTON_SAMPLE_LENGTH_UP, EDIT_BUTTON_SAMPLE_LENGTH_DOWN, - // This modifies offset, BPM, and stop segment changes. - EDIT_BUTTON_ADJUST_FINE, + EDIT_BUTTON_ADJUST_FINE, /**< This button modifies offset, BPM, and stop segment changes. */ EDIT_BUTTON_SAVE, /**< Save the present changes into the chart. */ @@ -166,7 +165,9 @@ struct MapEditToDI } }; -// Like MapEditToDI, but maps GameButton instead of DeviceInput. +/** + * @brief This is similar to MapEditToDI, + * but maps GameButton instead of DeviceInput. */ struct MapEditButtonToMenuButton { GameButton button[NUM_EditButton][NUM_EDIT_TO_MENU_SLOTS]; @@ -214,11 +215,14 @@ protected: // Call this before modifying m_NoteDataEdit. void SaveUndo(); - // Revert m_NoteDataEdit using m_Undo. + /** @brief Revert the last change made to m_NoteDataEdit. */ void Undo(); + /** @brief Remove the previously stored NoteData to prevent undoing. */ void ClearUndo(); - // Call this after modifying m_NoteDataEdit. It will Undo() if - // MAX_NOTES_PER_MEASURE was exceeded. + /** + * @brief This is to be called after modifying m_NoteDataEdit. + * + * It will Undo itself if MAX_NOTES_PER_MEASURE was exceeded. */ void CheckNumberOfNotesAndUndo(); void OnSnapModeChange(); @@ -252,7 +256,10 @@ protected: // keep track of where we are and what we're doing float m_fTrailingBeat; // this approaches GAMESTATE->m_fSongBeat, which is the actual beat - // The location we were at when shift was pressed, or -1 when shift isn't pressed: + /** + * @brief The location we were at when shift was pressed. + * + * If shift wasn't pressed, this will be -1. */ int m_iShiftAnchor; /** @brief The NoteData that has been cut or copied. */ @@ -311,22 +318,23 @@ protected: ThemeMetric EDIT_MODE; public: + /** @brief What are the choices that one can make on the main menu? */ enum MainMenuChoice { play_selection, set_selection_start, set_selection_end, edit_steps_information, - play_whole_song, + play_whole_song, /**< Play the entire chart from the beginning. */ play_selection_start_to_end, play_current_beat_to_end, - save, + save, /**< Save the current chart to disk. */ revert_to_last_save, revert_from_disk, - options, - edit_song_info, - edit_timing_data, - play_preview_music, + options, /**< Modify the PlayerOptions and SongOptions. */ + edit_song_info, /**< Edit some general information about the song. */ + edit_timing_data, /**< Edit the chart's timing data. */ + play_preview_music, /**< Play the song's preview music. */ exit, save_on_exit, NUM_MAIN_MENU_CHOICES, @@ -361,13 +369,14 @@ public: }; void HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAnswers, bool bAllowUndo = true ); void HandleAreaMenuChoice( AreaMenuChoice c, bool bAllowUndo = true ) { const vector v; HandleAreaMenuChoice( c, v, bAllowUndo ); } + /** @brief How should the selected notes be transformed? */ enum TurnType { - left, - right, - mirror, - shuffle, - super_shuffle, + left, /**< Turn the notes as if you were facing to the left. */ + right, /**< Turn the notes as if you were facing to the right. */ + mirror, /**< Turn the notes as if you were facing away from the machine. */ + shuffle, /**< Replace one column with another column. */ + super_shuffle, /**< Replace each note individually. */ NUM_TURN_TYPES }; enum TransformType @@ -421,10 +430,10 @@ public: { difficulty, meter, - description, - chartstyle, - step_credit, - predict_meter, + description, /**< What is the description of this chart? */ + chartstyle, /**< How is this chart meant to be played? */ + step_credit, /**< Who wrote this individual chart? */ + predict_meter, /**< What does the game think this chart's rating should be? */ tap_notes, jumps, hands, From 06a6e9991ac0dd1446935671f1b65ba1a0e2a867 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 14:39:13 -0400 Subject: [PATCH 022/333] Possible misnomer: Lifts aren't "taps". I know, you can cycle to lifts as a tap type. I think we need a better naming scheme here. --- src/NoteData.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NoteData.cpp b/src/NoteData.cpp index 88c350b408..eac5bc42b4 100644 --- a/src/NoteData.cpp +++ b/src/NoteData.cpp @@ -466,7 +466,8 @@ int NoteData::GetNumTapNotes( int iStartIndex, int iEndIndex ) const FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( *this, t, r, iStartIndex, iEndIndex ) { const TapNote &tn = GetTapNote(t, r); - if( tn.type != TapNote::empty && tn.type != TapNote::mine && tn.type != TapNote::fake ) + if( tn.type != TapNote::empty && tn.type != TapNote::mine + && tn.type != TapNote::lift && tn.type != TapNote::fake ) iNumNotes++; } } From c4c9d0c997b41e7ab64bae3084c34f72ecce6c4a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 14:40:49 -0400 Subject: [PATCH 023/333] Adjust the scoring formulas for prev commit. --- Themes/_fallback/Scripts/04 Scoring.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/_fallback/Scripts/04 Scoring.lua b/Themes/_fallback/Scripts/04 Scoring.lua index c0bf2b9bda..b6d68abb9c 100644 --- a/Themes/_fallback/Scripts/04 Scoring.lua +++ b/Themes/_fallback/Scripts/04 Scoring.lua @@ -11,6 +11,7 @@ function GetTotalItems(radars) return radars:GetValue('RadarCategory_TapsAndHolds') + radars:GetValue('RadarCategory_Holds') + radars:GetValue('RadarCategory_Rolls'); + + radars:GetValue('RadarCategory_Lifts'); end; -- Determine whether marvelous timing is to be considered. From aeb1f5e816b0fe9b8847887222a7afc6482e8f68 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 14:44:19 -0400 Subject: [PATCH 024/333] Holdover from older commit: didn't have to sub 1. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8f02b58eb9..65843ae9f9 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3135,7 +3135,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns } g_StepsInformation.rows[difficulty].iDefaultChoice = pSteps->GetDifficulty(); g_StepsInformation.rows[difficulty].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full); - g_StepsInformation.rows[meter].SetOneUnthemedChoice( ssprintf("%d", pSteps->GetMeter()-1) ); + g_StepsInformation.rows[meter].SetOneUnthemedChoice( ssprintf("%d", pSteps->GetMeter()) ); g_StepsInformation.rows[meter].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Home); g_StepsInformation.rows[predict_meter].SetOneUnthemedChoice( ssprintf("%.2f",pSteps->PredictMeter()) ); g_StepsInformation.rows[description].bEnabled = (EDIT_MODE.GetValue() >= EditMode_Full); From 71bf72e964b375481701332c0323e2bee17c2a7a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 20:48:23 -0400 Subject: [PATCH 025/333] [splittiming] More error fixes. (153) Nothing has been tied to the steps yet. --- src/NotesLoaderBMS.cpp | 12 ++++----- src/NotesLoaderKSF.cpp | 24 +++++++++--------- src/NotesLoaderMidi.cpp | 4 +-- src/NotesLoaderPMS.cpp | 12 ++++----- src/NotesLoaderSMA.cpp | 4 +-- src/NotesLoaderSSC.cpp | 26 ++++++++++---------- src/NotesWriterSSC.cpp | 54 ++++++++++++++++++++--------------------- 7 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index 4a95e85d57..9eb58168ed 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -799,7 +799,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( PREFSMAN->m_bQuirksMode ) { BPMSegment newSeg( 0, fBPM ); - out.AddBPMSegment( newSeg ); + out.m_SongTiming.AddBPMSegment( newSeg ); if( fBPM > 0.0f ) LOG->Trace( "Inserting new positive BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); else @@ -810,7 +810,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( fBPM > 0.0f ) { BPMSegment newSeg( 0, fBPM ); - out.AddBPMSegment( newSeg ); + out.m_SongTiming.AddBPMSegment( newSeg ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); } else @@ -901,7 +901,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur case BMS_TRACK_BPM: if( iVal > 0 ) { - out.SetBPMAtBeat( fBeat, (float) iVal ); + out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal ); } else @@ -918,7 +918,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) ) { float fBPM = StringToFloat( sBPM ); - out.SetBPMAtBeat( fBeat, fBPM ); + out.m_SongTiming.SetBPMAtBeat( fBeat, fBPM ); } else { @@ -937,12 +937,12 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) ) { // find the BPM at the time of this freeze - float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f; + float fBPS = out.m_SongTiming.GetBPMAtBeat(fBeat) / 60.0f; float fBeats = StringToFloat( sBeats ) / 48.0f; float fFreezeSecs = fBeats / fBPS; StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs ); - out.AddStopSegment( newSeg ); + out.m_SongTiming.AddStopSegment( newSeg ); LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds ); } else diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index b1732cdf81..14e6b4bca7 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -358,7 +358,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant else if( sValueName=="BPM" ) { BPM1 = StringToFloat(sParams[1]); - out.AddBPMSegment( BPMSegment(0, BPM1) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(0, BPM1) ); } else if( sValueName=="BPM2" ) { @@ -383,7 +383,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant else if( sValueName=="STARTTIME" ) { SMGap1 = -StringToFloat( sParams[1] )/100; - out.m_Timing.m_fBeat0OffsetInSeconds = SMGap1; + out.m_SongTiming.m_fBeat0OffsetInSeconds = SMGap1; } // This is currently required for more accurate KIU BPM changes. else if( sValueName=="STARTTIME2" ) @@ -409,7 +409,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant TickcountSegment tcs; tcs.m_iStartRow = BeatToNoteRow(0.0f); tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount; - out.m_Timing.AddTickcountSegment( tcs ); + out.m_SongTiming.AddTickcountSegment( tcs ); } else if ( sValueName=="STEP" ) { @@ -469,7 +469,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant const float beat = (BPMPos2 + SMGap1) * BeatsPerSecond; LOG->Trace( "BPM %f, BPS %f, BPMPos2 %f, beat %f", BPM1, BeatsPerSecond, BPMPos2, beat ); - out.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) ); } if( BPM3 > 0 && BPMPos3 > 0 ) @@ -479,7 +479,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant const float beat = (BPMPos3 + SMGap2) * BeatsPerSecond; LOG->Trace( "BPM %f, BPS %f, BPMPos3 %f, beat %f", BPM2, BeatsPerSecond, BPMPos3, beat ); - out.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) ); } } else @@ -515,7 +515,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant TickcountSegment tcs; tcs.m_iStartRow = BeatToNoteRow(fCurBeat); tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount; - out.m_Timing.AddTickcountSegment( tcs ); + out.m_SongTiming.AddTickcountSegment( tcs ); continue; } @@ -523,22 +523,22 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant { float fCurBpm = (float)numTemp; //out.m_Timing.AddBPMSegment( BPMSegment( BeatToNoteRow(fCurBeat), (float)numTemp ) ); - out.m_Timing.SetBPMAtBeat( fCurBeat, fCurBpm ); + out.m_SongTiming.SetBPMAtBeat( fCurBeat, fCurBpm ); continue; } else if (BeginsWith(NoteRowString, "|E")) { // Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster - float fCurDelay = 60 / out.m_Timing.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount; - fCurDelay += out.m_Timing.GetStopAtRow(BeatToNoteRow(fCurBeat) ); - out.m_Timing.SetStopAtBeat( fCurBeat, fCurDelay, true ); + float fCurDelay = 60 / out.m_SongTiming.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount; + fCurDelay += out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) ); + out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true ); continue; } else if (BeginsWith(NoteRowString, "|D")) { - float fCurDelay = out.m_Timing.GetStopAtRow(BeatToNoteRow(fCurBeat) ); + float fCurDelay = out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) ); fCurDelay += (float)numTemp / 1000; - out.m_Timing.SetStopAtBeat( fCurBeat, fCurDelay, true ); + out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true ); continue; } } diff --git a/src/NotesLoaderMidi.cpp b/src/NotesLoaderMidi.cpp index a74b3610a8..ef354d7bfe 100644 --- a/src/NotesLoaderMidi.cpp +++ b/src/NotesLoaderMidi.cpp @@ -682,7 +682,7 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut ) double fSecondsPerBeat = (iter->tickSeconds * GUITAR_MIDI_COUNTS_PER_BEAT); bpmSeg.m_fBPS = float( 1. / fSecondsPerBeat ); - songOut.m_Timing.AddBPMSegment( bpmSeg ); + songOut.m_SongTiming.AddBPMSegment( bpmSeg ); } FOREACH_CONST( MidiFileIn::TimeSignatureChange, midi.timeSignatureEvents_, iter ) @@ -692,7 +692,7 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut ) seg.m_iNumerator = iter->numerator; seg.m_iDenominator = iter->denominator; - songOut.m_Timing.AddTimeSignatureSegment( seg ); + songOut.m_SongTiming.AddTimeSignatureSegment( seg ); } diff --git a/src/NotesLoaderPMS.cpp b/src/NotesLoaderPMS.cpp index b733aa3d9f..44a125e1cb 100644 --- a/src/NotesLoaderPMS.cpp +++ b/src/NotesLoaderPMS.cpp @@ -591,7 +591,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( fBPM > 0.0f ) { BPMSegment newSeg( 0, fBPM ); - out.AddBPMSegment( newSeg ); + out.m_SongTiming.AddBPMSegment( newSeg ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); } else @@ -673,7 +673,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur case PMS_TRACK_BPM: if( iVal > 0 ) { - out.SetBPMAtBeat( fBeat, (float) iVal ); + out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal ); } else @@ -694,7 +694,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( fBPM > 0.0f ) { BPMSegment newSeg( BeatToNoteRow(fBeat), fBPM ); - out.AddBPMSegment( newSeg ); + out.m_SongTiming.AddBPMSegment( newSeg ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() ); } else @@ -716,12 +716,12 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) ) { // find the BPM at the time of this freeze - float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f; + float fBPS = out.m_SongTiming.GetBPMAtBeat(fBeat) / 60.0f; float fBeats = StringToFloat( sBeats ) / 48.0f; float fFreezeSecs = fBeats / fBPS; StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs ); - out.AddStopSegment( newSeg ); + out.m_SongTiming.AddStopSegment( newSeg ); LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds ); } else @@ -750,7 +750,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( fBPM > 0.0f ) { BPMSegment newSeg( iStepIndex, fBPM ); - out.AddBPMSegment( newSeg ); + out.m_SongTiming.AddBPMSegment( newSeg ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() ); } diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 93dcb65095..1fa083136d 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -113,8 +113,8 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) return false; } - out.m_Timing.m_sFile = sPath; - LoadTimingFromSMAFile( msd, out.m_Timing ); + out.m_SongTiming.m_sFile = sPath; + LoadTimingFromSMAFile( msd, out.m_SongTiming ); for( unsigned i=0; i 0.0f) { // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.m_Timing.AddStopSegment( new_seg ); + out.m_SongTiming.AddStopSegment( new_seg ); } else { @@ -420,7 +420,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach if( PREFSMAN->m_bQuirksMode ) { // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.m_Timing.AddStopSegment( new_seg ); + out.m_SongTiming.AddStopSegment( new_seg ); } else LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); @@ -452,7 +452,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); if(fFreezeSeconds > 0.0f) - out.m_Timing.AddStopSegment( new_seg ); + out.m_SongTiming.AddStopSegment( new_seg ); else LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); } @@ -479,13 +479,13 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); if(fNewBPM > 0.0f) - out.m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); else { - out.m_Timing.m_bHasNegativeBpms = true; + out.m_SongTiming.m_bHasNegativeBpms = true; // only add Negative BPMs in quirks mode -aj if( PREFSMAN->m_bQuirksMode ) - out.m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); + out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); else LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM ); } @@ -513,7 +513,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach const float fNewBeat = StringToFloat( arrayWarpValues[1] ); if(fNewBeat > fBeat) - out.m_Timing.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); + out.m_SongTiming.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); else { LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat ); @@ -541,7 +541,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach RString sLabel = arrayLabelValues[1]; TrimRight(sLabel); if( fBeat >= 0.0f ) - out.m_Timing.AddLabelSegment( LabelSegment(fBeat, sLabel) ); + out.m_SongTiming.AddLabelSegment( LabelSegment(fBeat, sLabel) ); else { LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() ); @@ -591,7 +591,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach continue; } - out.m_Timing.AddTimeSignatureSegment( seg ); + out.m_SongTiming.AddTimeSignatureSegment( seg ); } } @@ -619,7 +619,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants { // LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks ); - out.m_Timing.AddTickcountSegment( new_seg ); + out.m_SongTiming.AddTickcountSegment( new_seg ); } else { @@ -646,7 +646,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach const float fComboBeat = StringToFloat( arrayComboValues[0] ); const int iCombos = atoi( arrayComboValues[1] ); ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); - out.m_Timing.AddComboSegment( new_seg ); + out.m_SongTiming.AddComboSegment( new_seg ); } } diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 69ca696756..3c4ff71a3b 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -74,7 +74,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.PutLine( "#INSTRUMENTTRACK:" + s + ";\n" ); } } - f.PutLine( ssprintf( "#OFFSET:%.6f;", out.m_Timing.m_fBeat0OffsetInSeconds ) ); + f.PutLine( ssprintf( "#OFFSET:%.6f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.6f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.6f;", out.m_fMusicSampleLengthSeconds ) ); if( out.m_fSpecifiedLastBeat > 0 ) @@ -107,39 +107,39 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) } f.Write( "#BPMS:" ); - for( unsigned i=0; im_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) ); vector::const_iterator iter2 = iter; iter2++; - if( iter2 != out.m_Timing.m_vTimeSignatureSegments.end() ) + if( iter2 != out.m_SongTiming.m_vTimeSignatureSegments.end() ) f.Write( "," ); } f.PutLine( ";" ); - ASSERT( !out.m_Timing.m_TickcountSegments.empty() ); + ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() ); f.Write( "#TICKCOUNTS:" ); - for( unsigned i=0; i Date: Mon, 9 May 2011 21:03:30 -0400 Subject: [PATCH 026/333] [splittiming] Bringing it down. (91) --- src/AdjustSync.cpp | 24 ++++++++++++------------ src/Background.cpp | 6 +++--- src/GameplayAssist.cpp | 2 +- src/MeterDisplay.cpp | 4 ++-- src/NoteField.cpp | 18 +++++++++--------- src/Player.cpp | 24 ++++++++++++------------ src/ScoreKeeperNormal.cpp | 4 ++-- src/ScreenGameplay.cpp | 2 +- src/ScreenSelectMusic.cpp | 2 +- src/Song.cpp | 32 ++++++++++++++++---------------- 10 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/AdjustSync.cpp b/src/AdjustSync.cpp index e669f9cb74..b375928a25 100644 --- a/src/AdjustSync.cpp +++ b/src/AdjustSync.cpp @@ -58,7 +58,7 @@ void AdjustSync::ResetOriginalSyncData() s_pTimingDataOriginal = new TimingData; if( GAMESTATE->m_pCurSong ) - *s_pTimingDataOriginal = GAMESTATE->m_pCurSong->m_Timing; + *s_pTimingDataOriginal = GAMESTATE->m_pCurSong->m_SongTiming; else *s_pTimingDataOriginal = TimingData(); s_fGlobalOffsetSecondsOriginal = PREFSMAN->m_fGlobalOffsetSeconds; @@ -87,7 +87,7 @@ void AdjustSync::SaveSyncChanges() { if( GAMESTATE->IsCourseMode() ) return; - if( GAMESTATE->m_pCurSong && *s_pTimingDataOriginal != GAMESTATE->m_pCurSong->m_Timing ) + if( GAMESTATE->m_pCurSong && *s_pTimingDataOriginal != GAMESTATE->m_pCurSong->m_SongTiming ) { if( GAMESTATE->IsEditing() ) { @@ -110,7 +110,7 @@ void AdjustSync::RevertSyncChanges() if( GAMESTATE->IsCourseMode() ) return; PREFSMAN->m_fGlobalOffsetSeconds.Set( s_fGlobalOffsetSecondsOriginal ); - GAMESTATE->m_pCurSong->m_Timing = *s_pTimingDataOriginal; + GAMESTATE->m_pCurSong->m_SongTiming = *s_pTimingDataOriginal; ResetOriginalSyncData(); s_fStandardDeviation = 0.0f; s_fAverageError = 0.0f; @@ -186,7 +186,7 @@ void AdjustSync::AutosyncOffset() switch( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType ) { case SongOptions::AUTOSYNC_SONG: - GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += mean; + GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += mean; break; case SongOptions::AUTOSYNC_MACHINE: PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + mean ); @@ -232,15 +232,15 @@ void AdjustSync::AutosyncTempo() if( !CalcLeastSquares( s_vAutosyncTempoData, fSlope, fIntercept, fFilteredError ) ) return; - GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += fIntercept; + GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept; const float fScaleBPM = 1.0f/(1.0f - fSlope); - FOREACH( BPMSegment, GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments, i ) + FOREACH( BPMSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments, i ) i->SetBPM( i->GetBPM() * fScaleBPM ); // We assume that the stops were measured as a number of beats. // Therefore, if we change the bpms, we need to make a similar // change to the stops. - FOREACH( StopSegment, GAMESTATE->m_pCurSong->m_Timing.m_StopSegments, i ) + FOREACH( StopSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments, i ) i->m_fStopSeconds *= 1.0f - fSlope; SCREENMAN->SystemMessage( AUTOSYNC_CORRECTION_APPLIED.GetValue() ); @@ -296,7 +296,7 @@ void AdjustSync::GetSyncChangeTextSong( vector &vsAddTo ) { float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_fBeat0OffsetInSeconds, 0.001f ); - float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds, 0.001f ); + float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds, 0.001f ); float fDelta = fNew - fOld; if( fabsf(fDelta) > 0.0001f ) @@ -309,10 +309,10 @@ void AdjustSync::GetSyncChangeTextSong( vector &vsAddTo ) } } - for( unsigned i=0; im_pCurSong->m_Timing.m_BPMSegments.size(); i++ ) + for( unsigned i=0; im_pCurSong->m_SongTiming.m_BPMSegments.size(); i++ ) { float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_BPMSegments[i].GetBPM(), 0.001f ); - float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments[i].GetBPM(), 0.001f ); + float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments[i].GetBPM(), 0.001f ); float fDelta = fNew - fOld; if( fabsf(fDelta) > 0.0001f ) @@ -330,10 +330,10 @@ void AdjustSync::GetSyncChangeTextSong( vector &vsAddTo ) } } - for( unsigned i=0; im_pCurSong->m_Timing.m_StopSegments.size(); i++ ) + for( unsigned i=0; im_pCurSong->m_SongTiming.m_StopSegments.size(); i++ ) { float fOld = Quantize( AdjustSync::s_pTimingDataOriginal->m_StopSegments[i].m_fStopSeconds, 0.001f ); - float fNew = Quantize( GAMESTATE->m_pCurSong->m_Timing.m_StopSegments[i].m_fStopSeconds, 0.001f ); + float fNew = Quantize( GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds, 0.001f ); float fDelta = fNew - fOld; if( fabsf(fDelta) > 0.0001f ) diff --git a/src/Background.cpp b/src/Background.cpp index 34050aedcc..5047e5fc1e 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -419,7 +419,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac int iStartRow = BeatToNoteRow(fFirstBeat); int iEndRow = BeatToNoteRow(fEndBeat); - const TimingData &timing = m_pSong->m_Timing; + const TimingData &timing = m_pSong->m_SongTiming; // change BG every time signature change or 4 measures FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter ) @@ -697,7 +697,7 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus float fBeat, fBPS, fThrowAway; bool bFreeze; int iThrowAway; - pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway, fThrowAway ); + pSong->m_SongTiming.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway, fThrowAway ); // Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. const float fRate = GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; @@ -762,7 +762,7 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus m_pCurrentBGA->PlayCommand( "GainFocus" ); /* How much time of this BGA have we skipped? (This happens with SetSeconds.) */ - const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat ); + const float fStartSecond = pSong->m_SongTiming.GetElapsedTimeFromBeat( change.m_fStartBeat ); /* This is affected by the music rate. */ fDeltaTime = fCurrentTime - fStartSecond; diff --git a/src/GameplayAssist.cpp b/src/GameplayAssist.cpp index 7531c77e43..97a324416d 100644 --- a/src/GameplayAssist.cpp +++ b/src/GameplayAssist.cpp @@ -27,7 +27,7 @@ void GameplayAssist::PlayTicks( const NoteData &nd ) * come out on time; the actual precise timing is handled by SetStartTime. */ float fPositionSeconds = GAMESTATE->m_fMusicSeconds; fPositionSeconds += SOUNDMAN->GetPlayLatency() + (float)CommonMetrics::TICK_EARLY_SECONDS + 0.250f; - const TimingData &timing = GAMESTATE->m_pCurSong->m_Timing; + const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; const float fSongBeat = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); const int iSongRow = max( 0, BeatToNoteRowNotRounded( fSongBeat ) ); diff --git a/src/MeterDisplay.cpp b/src/MeterDisplay.cpp index 3018125cd1..66c0b19587 100644 --- a/src/MeterDisplay.cpp +++ b/src/MeterDisplay.cpp @@ -73,8 +73,8 @@ void SongMeterDisplay::Update( float fDeltaTime ) { if( GAMESTATE->m_pCurSong ) { - float fSongStartSeconds = GAMESTATE->m_pCurSong->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat ); - float fSongEndSeconds = GAMESTATE->m_pCurSong->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); + float fSongStartSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat ); + float fSongEndSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); float fPercentPositionSong = SCALE( GAMESTATE->m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f ); CLAMP( fPercentPositionSong, 0, 1 ); diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 6895b07234..213d5e1e09 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -742,7 +742,7 @@ void NoteField::DrawPrimitives() // Draw beat bars if( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) { - const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_Timing.m_vTimeSignatureSegments; + const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_SongTiming.m_vTimeSignatureSegments; int iMeasureIndex = 0; FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter ) { @@ -786,7 +786,7 @@ void NoteField::DrawPrimitives() ASSERT(GAMESTATE->m_pCurSong); // BPM text - FOREACH_CONST( BPMSegment, GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments, seg ) + FOREACH_CONST( BPMSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -797,7 +797,7 @@ void NoteField::DrawPrimitives() } // Freeze text - FOREACH_CONST( StopSegment, GAMESTATE->m_pCurSong->m_Timing.m_StopSegments, seg ) + FOREACH_CONST( StopSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -808,7 +808,7 @@ void NoteField::DrawPrimitives() } // Warp text - FOREACH_CONST( WarpSegment, GAMESTATE->m_pCurSong->m_Timing.m_WarpSegments, seg ) + FOREACH_CONST( WarpSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_WarpSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -819,7 +819,7 @@ void NoteField::DrawPrimitives() } // Time Signature text - FOREACH_CONST( TimeSignatureSegment, GAMESTATE->m_pCurSong->m_Timing.m_vTimeSignatureSegments, seg ) + FOREACH_CONST( TimeSignatureSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_vTimeSignatureSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -830,7 +830,7 @@ void NoteField::DrawPrimitives() } // Tickcount text - FOREACH_CONST( TickcountSegment, GAMESTATE->m_pCurSong->m_Timing.m_TickcountSegments, seg ) + FOREACH_CONST( TickcountSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_TickcountSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -841,7 +841,7 @@ void NoteField::DrawPrimitives() } // Combo text - FOREACH_CONST( ComboSegment, GAMESTATE->m_pCurSong->m_Timing.m_ComboSegments, seg ) + FOREACH_CONST( ComboSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_ComboSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -852,7 +852,7 @@ void NoteField::DrawPrimitives() } // Label text - FOREACH_CONST( LabelSegment, GAMESTATE->m_pCurSong->m_Timing.m_LabelSegments, seg ) + FOREACH_CONST( LabelSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_LabelSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -872,7 +872,7 @@ void NoteField::DrawPrimitives() FOREACH_CONST( Attack, ce.attacks, a ) { float fSecond = a->fStartSecond; - float fBeat = GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( fSecond ); + float fBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fSecond ); if( BeatToNoteRow(fBeat) >= iFirstRowToDraw && BeatToNoteRow(fBeat) <= iLastRowToDraw) diff --git a/src/Player.cpp b/src/Player.cpp index 570112bb0e..caa30e5c92 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1528,7 +1528,7 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool // Is this the row we want? do { const TapNote &tn = begin->second; - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( begin->first ) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( begin->first ) ) break; if( tn.type == TapNote::empty ) break; @@ -1579,7 +1579,7 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b ++iter; continue; } - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) ) { ++iter; continue; @@ -2011,8 +2011,8 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b * "jack hammers." Hmm. */ const int iStepSearchRows = max( - BeatToNoteRow( GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, - iSongRow - BeatToNoteRow( GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) ) + BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, + iSongRow - BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) ) ) + ROWS_PER_BEAT; int iRowOfOverlappingNoteOrRow = row; if( row == -1 ) @@ -2089,7 +2089,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b // Stepped too close to mine? if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) && fSecondsFromExact <= GetWindowSeconds(TW_Mine) && - !GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iSongRow) ) + !GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iSongRow) ) score = TNS_HitMine; break; @@ -2564,7 +2564,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) float fThrowAway; int iWarpBeginRow; float fWarpLength; - GAMESTATE->m_pCurSong->m_Timing.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength ); + GAMESTATE->m_pCurSong->m_SongTiming.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength ); iMissIfOlderThanThisRow = BeatToNoteRow( fMissIfOlderThanThisBeat ); if( bFreeze || bDelay ) @@ -2587,7 +2587,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) continue; // Ignore all notes that are skipped via WARPS. - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) ) continue; if( tn.type == TapNote::mine ) @@ -2622,7 +2622,7 @@ void Player::UpdateJudgedRows() int iRow = iter.Row(); // If row is within a warp section, ignore it. -aj - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iRow) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iRow) ) continue; if( iLastSeenRow != iRow ) @@ -2843,13 +2843,13 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now ) int iCheckpointFrequencyRows = ROWS_PER_BEAT/2; if( CHECKPOINTS_USE_TICKCOUNTS ) { - int tickCurrent = GAMESTATE->m_pCurSong->m_Timing.GetTickcountAtRow( iLastRowCrossed ); + int tickCurrent = GAMESTATE->m_pCurSong->m_SongTiming.GetTickcountAtRow( iLastRowCrossed ); // There are some charts that don't want tickcounts involved at all. iCheckpointFrequencyRows = (tickCurrent > 0 ? ROWS_PER_BEAT / tickCurrent : 0); } else if( CHECKPOINTS_USE_TIME_SIGNATURES ) { - TimeSignatureSegment tSignature = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) ); + TimeSignatureSegment tSignature = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) ); // Most songs are in 4/4 time. The frequency for checking tick counts should reflect that. iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.m_iDenominator / (tSignature.m_iNumerator * 4); @@ -2957,7 +2957,7 @@ void Player::HandleTapRowScore( unsigned row ) #endif // Warp hackery. -aj - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( row ) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( row ) ) return; if( GAMESTATE->m_bDemonstrationOrJukebox ) @@ -3061,7 +3061,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH #endif // More warp hackery. -aj - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iRow ) ) + if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iRow ) ) return; // don't accumulate combo if AutoPlay is on. diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index b3e106bfaf..36c405501e 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -443,7 +443,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH if( iNumBreakCombo == 0 ) { - TimingData td = GAMESTATE->m_pCurSong->m_Timing; + TimingData td = GAMESTATE->m_pCurSong->m_SongTiming; int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier; } @@ -463,7 +463,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn if ( tns >= m_MinScoreToContinueCombo ) { m_pPlayerStageStats->m_iCurMissCombo = 0; - TimingData td = GAMESTATE->m_pCurSong->m_Timing; + TimingData td = GAMESTATE->m_pCurSong->m_SongTiming; int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier; } diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 1ac4b6d8c5..1a603c7046 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1423,7 +1423,7 @@ void ScreenGameplay::UpdateSongPosition( float fDeltaTime ) RageTimer tm; const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm ); const float fAdjust = SOUND->GetFrameTimingAdjustment( fDeltaTime ); - GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_Timing, tm+fAdjust ); + GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust ); } void ScreenGameplay::BeginScreen() diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index fe4aee3aab..4ecb227b3b 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1763,7 +1763,7 @@ void ScreenSelectMusic::AfterMusicChange() case SampleMusicPreviewMode_LastSong: // fall through // play the sample music m_sSampleMusicToPlay = pSong->GetMusicPath(); - m_pSampleMusicTimingData = &pSong->m_Timing; + m_pSampleMusicTimingData = &pSong->m_SongTiming; m_fSampleStartSeconds = pSong->m_fMusicSampleStartSeconds; m_fSampleLengthSeconds = pSong->m_fMusicSampleLengthSeconds; break; diff --git a/src/Song.cpp b/src/Song.cpp index 6d9022177b..b8882a5ef2 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -167,7 +167,7 @@ void Song::GetDisplayBpms( DisplayBpms &AddTo ) const else { float fMinBPM, fMaxBPM; - m_Timing.GetActualBPM( fMinBPM, fMaxBPM ); + m_SongTiming.GetActualBPM( fMinBPM, fMaxBPM ); AddTo.Add( fMinBPM ); AddTo.Add( fMaxBPM ); } @@ -488,16 +488,16 @@ void Song::TidyUpData() m_sArtist = "Unknown artist"; TranslateTitles(); - if( m_Timing.m_BPMSegments.empty() ) + if( m_SongTiming.m_BPMSegments.empty() ) { LOG->UserLog( "Song file", m_sSongDir + m_sSongFileName, "has no BPM segments, default provided." ); - m_Timing.AddBPMSegment( BPMSegment(0, 60) ); + m_SongTiming.AddBPMSegment( BPMSegment(0, 60) ); } // Make sure the first BPM segment starts at beat 0. - if( m_Timing.m_BPMSegments[0].m_iStartRow != 0 ) - m_Timing.m_BPMSegments[0].m_iStartRow = 0; + if( m_SongTiming.m_BPMSegments[0].m_iStartRow != 0 ) + m_SongTiming.m_BPMSegments[0].m_iStartRow = 0; if( m_fMusicSampleStartSeconds == -1 || @@ -791,10 +791,10 @@ void Song::TidyUpData() } // If no time signature specified, assume 4/4 time for the whole song. - if( m_Timing.m_vTimeSignatureSegments.empty() ) + if( m_SongTiming.m_vTimeSignatureSegments.empty() ) { TimeSignatureSegment seg(0, 4, 4); - m_Timing.m_vTimeSignatureSegments.push_back( seg ); + m_SongTiming.m_vTimeSignatureSegments.push_back( seg ); } /* @@ -802,24 +802,24 @@ void Song::TidyUpData() * per beat for the entire song. The default of 2 is chosen more * for compatibility with the Pump Pro series than anything else. */ - if( m_Timing.m_TickcountSegments.empty() ) + if( m_SongTiming.m_TickcountSegments.empty() ) { TickcountSegment seg(0, 2); - m_Timing.m_TickcountSegments.push_back( seg ); + m_SongTiming.m_TickcountSegments.push_back( seg ); } // Have a default combo segment of one just in case. - if( m_Timing.m_ComboSegments.empty() ) + if( m_SongTiming.m_ComboSegments.empty() ) { ComboSegment seg(0, 1); - m_Timing.m_ComboSegments.push_back( seg ); + m_SongTiming.m_ComboSegments.push_back( seg ); } // Have a default label segment just in case. - if( m_Timing.m_LabelSegments.empty() ) + if( m_SongTiming.m_LabelSegments.empty() ) { LabelSegment seg(0, "Song Start"); - m_Timing.m_LabelSegments.push_back( seg ); + m_SongTiming.m_LabelSegments.push_back( seg ); } } @@ -1465,7 +1465,7 @@ bool Song::IsEditAlreadyLoaded( Steps* pSteps ) const bool Song::HasSignificantBpmChangesOrStops() const { - if( m_Timing.HasStops() ) + if( m_SongTiming.HasStops() ) return true; // Don't consider BPM changes that only are only for maintaining sync as @@ -1475,7 +1475,7 @@ bool Song::HasSignificantBpmChangesOrStops() const if( m_fSpecifiedBPMMin != m_fSpecifiedBPMMax ) return true; } - else if( m_Timing.HasBpmChanges() ) + else if( m_SongTiming.HasBpmChanges() ) { return true; } @@ -1568,7 +1568,7 @@ public: } static int GetTimingData( T* p, lua_State *L ) { - p->m_Timing.PushSelf(L); + p->m_SongTiming.PushSelf(L); return 1; } // has functions From 9cb41af5f4b1e349874f8e2d64b9ba79eed99845 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 21:11:33 -0400 Subject: [PATCH 027/333] [splittiming] All but ScreenEdit. (67) --- src/Attack.cpp | 12 +++++++----- src/AutoKeysounds.cpp | 2 +- src/Foreground.cpp | 6 +++--- src/GameSoundManager.cpp | 4 ++-- src/LyricDisplay.cpp | 2 +- src/NoteDataUtil.cpp | 4 ++-- src/Player.cpp | 4 ++-- src/ScreenGameplay.cpp | 6 +++--- src/ScreenHowToPlay.cpp | 2 +- src/ScreenSyncOverlay.cpp | 4 ++-- src/Song.cpp | 8 +++++--- 11 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/Attack.cpp b/src/Attack.cpp index a896944158..1a67cc3181 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -11,9 +11,10 @@ void Attack::GetAttackBeats( const Song *pSong, float &fStartBeat, float &fEndBe { ASSERT( pSong ); ASSERT_M( fStartSecond >= 0, ssprintf("StartSecond: %f",fStartSecond) ); - - fStartBeat = pSong->GetBeatFromElapsedTime( fStartSecond ); - fEndBeat = pSong->GetBeatFromElapsedTime( fStartSecond+fSecsRemaining ); + + const TimingData &timing = pSong->m_SongTiming; + fStartBeat = timing.GetBeatFromElapsedTime( fStartSecond ); + fEndBeat = timing.GetBeatFromElapsedTime( fStartSecond+fSecsRemaining ); } /* Get the range for an attack that's being applied in realtime, eg. during battle @@ -34,9 +35,10 @@ void Attack::GetRealtimeAttackBeats( const Song *pSong, const PlayerState* pPlay fStartBeat = min( GAMESTATE->m_fSongBeat+8, pPlayerState->m_fLastDrawnBeat ); fStartBeat = truncf(fStartBeat)+1; - const float lStartSecond = pSong->GetElapsedTimeFromBeat( fStartBeat ); + const TimingData &timing = pSong->m_SongTiming; + const float lStartSecond = timing.GetElapsedTimeFromBeat( fStartBeat ); const float fEndSecond = lStartSecond + fSecsRemaining; - fEndBeat = pSong->GetBeatFromElapsedTime( fEndSecond ); + fEndBeat = timing.GetBeatFromElapsedTime( fEndSecond ); fEndBeat = truncf(fEndBeat)+1; // loading the course should have caught this. diff --git a/src/AutoKeysounds.cpp b/src/AutoKeysounds.cpp index 5aac67976b..aba066200d 100644 --- a/src/AutoKeysounds.cpp +++ b/src/AutoKeysounds.cpp @@ -99,7 +99,7 @@ void AutoKeysounds::LoadAutoplaySoundsInto( RageSoundReader_Chain *pChain ) if( tn[pn].iKeysoundIndex >= 0 ) { RString sKeysoundFilePath = sSongDir + pSong->m_vsKeysoundFile[tn[pn].iKeysoundIndex]; - float fSeconds = pSong->m_Timing.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency(); + float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency(); float fPan = 0; if( !bSoundIsGlobal ) diff --git a/src/Foreground.cpp b/src/Foreground.cpp index 708fbcb608..54ba873d7e 100644 --- a/src/Foreground.cpp +++ b/src/Foreground.cpp @@ -41,9 +41,9 @@ void Foreground::LoadFromSong( const Song *pSong ) bga.m_fStartBeat = change.m_fStartBeat; bga.m_bFinished = false; - const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( bga.m_fStartBeat ); + const float fStartSecond = pSong->m_SongTiming.GetElapsedTimeFromBeat( bga.m_fStartBeat ); const float fStopSecond = fStartSecond + bga.m_bga->GetTweenTimeLeft(); - bga.m_fStopBeat = pSong->m_Timing.GetBeatFromElapsedTime( fStopSecond ); + bga.m_fStopBeat = pSong->m_SongTiming.GetBeatFromElapsedTime( fStopSecond ); bga.m_bga->SetVisible( false ); @@ -82,7 +82,7 @@ void Foreground::Update( float fDeltaTime ) bga.m_bga->SetVisible( true ); bga.m_bga->PlayCommand( "On" ); - const float fStartSecond = m_pSong->m_Timing.GetElapsedTimeFromBeat( bga.m_fStartBeat ); + const float fStartSecond = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( bga.m_fStartBeat ); lDeltaTime = GAMESTATE->m_fMusicSeconds - fStartSecond; } else diff --git a/src/GameSoundManager.cpp b/src/GameSoundManager.cpp index 5b3ba858de..6e517249fb 100644 --- a/src/GameSoundManager.cpp +++ b/src/GameSoundManager.cpp @@ -146,7 +146,7 @@ static void StartMusic( MusicToPlay &ToPlay ) SSCLoader::LoadFromSSCFile(ToPlay.m_sTimingFile, song) ) { ToPlay.HasTiming = true; - ToPlay.m_TimingData = song.m_Timing; + ToPlay.m_TimingData = song.m_SongTiming; // get cabinet lights if any Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, StepsType_lights_cabinet ); if( pStepsCabinetLights ) @@ -156,7 +156,7 @@ static void StartMusic( MusicToPlay &ToPlay ) SMLoader::LoadFromSMFile(ToPlay.m_sTimingFile, song) ) { ToPlay.HasTiming = true; - ToPlay.m_TimingData = song.m_Timing; + ToPlay.m_TimingData = song.m_SongTiming; // get cabinet lights if any Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, StepsType_lights_cabinet ); if( pStepsCabinetLights ) diff --git a/src/LyricDisplay.cpp b/src/LyricDisplay.cpp index 27263d068c..fec9827e34 100644 --- a/src/LyricDisplay.cpp +++ b/src/LyricDisplay.cpp @@ -59,7 +59,7 @@ void LyricDisplay::Update( float fDeltaTime ) if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() ) fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime; else - fEndTime = pSong->GetElapsedTimeFromBeat( pSong->m_fLastBeat ); + fEndTime = pSong->m_SongTiming.GetElapsedTimeFromBeat( pSong->m_fLastBeat ); const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime; const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue(); diff --git a/src/NoteDataUtil.cpp b/src/NoteDataUtil.cpp index 6b7f47cba1..413fd3a425 100644 --- a/src/NoteDataUtil.cpp +++ b/src/NoteDataUtil.cpp @@ -2215,7 +2215,7 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong ) for( float sec=15; secm_fMusicLengthSeconds; sec+=30 ) { - float fBeat = pSong->GetBeatFromElapsedTime( sec ); + float fBeat = pSong->m_SongTiming.GetBeatFromElapsedTime( sec ); int iBeat = (int)fBeat; int iTrack = iBeat % nd.GetNumTracks(); // deterministically calculates track TapNote tn( @@ -2448,7 +2448,7 @@ void NoteDataUtil::SetHopoPossibleFlags( const Song *pSong, NoteData& ndInOut ) FOREACH_NONEMPTY_ROW_ALL_TRACKS( ndInOut, r ) { float fBeat = NoteRowToBeat( r ); - float fSeconds = pSong->GetElapsedTimeFromBeat( fBeat ); + float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeat( fBeat ); int iLastTapTrack = ndInOut.GetLastTrackWithTapOrHoldHead( r ); if( iLastTapTrack != -1 && fSeconds <= fLastRowMusicSeconds + g_fTimingWindowHopo ) diff --git a/src/Player.cpp b/src/Player.cpp index caa30e5c92..2c793bb4c1 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1873,7 +1873,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b break; } - const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat; + const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat; const int iSongRow = row == -1 ? BeatToNoteRow( fSongBeat ) : row; if( col != -1 && !bRelease ) @@ -2039,7 +2039,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b float fNoteOffset = 0.0f; // we need this later if we are autosyncing const float fStepBeat = NoteRowToBeat( iRowOfOverlappingNoteOrRow ); - const float fStepSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(fStepBeat); + const float fStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat(fStepBeat); if( row == -1 ) { diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 1a603c7046..f2cba6c337 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1480,7 +1480,7 @@ bool ScreenGameplay::AllAreFailing() void ScreenGameplay::GetMusicEndTiming( float &fSecondsToStartFadingOutMusic, float &fSecondsToStartTransitioningOut ) { - float fLastStepSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); + float fLastStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); fLastStepSeconds += Player::GetMaxStepDistanceSeconds(); float fTransitionLength; @@ -1995,7 +1995,7 @@ void ScreenGameplay::SendCrossedMessages() static int iRowLastCrossed = 0; float fPositionSeconds = GAMESTATE->m_fMusicSeconds; - float fSongBeat = GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ); + float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ); int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); iRowNow = max( 0, iRowNow ); @@ -2033,7 +2033,7 @@ void ScreenGameplay::SendCrossedMessages() float fNoteWillCrossInSeconds = MESSAGE_SPACING_SECONDS * i; float fPositionSeconds = GAMESTATE->m_fMusicSeconds + fNoteWillCrossInSeconds; - float fSongBeat = GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ); + float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ); int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); iRowNow = max( 0, iRowNow ); diff --git a/src/ScreenHowToPlay.cpp b/src/ScreenHowToPlay.cpp index 7deca6dd40..877fb693c4 100644 --- a/src/ScreenHowToPlay.cpp +++ b/src/ScreenHowToPlay.cpp @@ -244,7 +244,7 @@ void ScreenHowToPlay::Update( float fDelta ) { if( GAMESTATE->m_pCurSong != NULL ) { - GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_Timing ); + GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_SongTiming ); m_fFakeSecondsIntoSong += fDelta; static int iLastNoteRowCounted = 0; diff --git a/src/ScreenSyncOverlay.cpp b/src/ScreenSyncOverlay.cpp index a0038b083f..baf240d54d 100644 --- a/src/ScreenSyncOverlay.cpp +++ b/src/ScreenSyncOverlay.cpp @@ -221,7 +221,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input ) } if( GAMESTATE->m_pCurSong != NULL ) { - BPMSegment& seg = GAMESTATE->m_pCurSong->GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat ); + BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat ); seg.m_fBPS += fDelta; } } @@ -253,7 +253,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input ) case ChangeSongOffset: if( GAMESTATE->m_pCurSong != NULL ) - GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += fDelta; + GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta; break; } } diff --git a/src/Song.cpp b/src/Song.cpp index b8882a5ef2..a2c5184425 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -504,13 +504,14 @@ void Song::TidyUpData() m_fMusicSampleStartSeconds == 0 || m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) { - m_fMusicSampleStartSeconds = this->GetElapsedTimeFromBeat( 100 ); + const TimingData &timing = this->m_SongTiming; + m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( 100 ); if( m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) { int iBeat = lrintf( m_fLastBeat/2 ); iBeat -= iBeat%4; - m_fMusicSampleStartSeconds = this->GetElapsedTimeFromBeat( (float)iBeat ); + m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( (float)iBeat ); } } @@ -1485,7 +1486,8 @@ bool Song::HasSignificantBpmChangesOrStops() const float Song::GetStepsSeconds() const { - return GetElapsedTimeFromBeat( m_fLastBeat ) - GetElapsedTimeFromBeat( m_fFirstBeat ); + const TimingData &timing = this->m_SongTiming; + return timing.GetElapsedTimeFromBeat( m_fLastBeat ) - timing.GetElapsedTimeFromBeat( m_fFirstBeat ); } bool Song::IsLong() const From cd9fc83029aa95a6519bd9cc2d01860d4bd84711 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 21:17:24 -0400 Subject: [PATCH 028/333] [splittiming] We can build now. How effective the build is, though...that's the question. Time to risk breaking more parts. --- src/ScreenEdit.cpp | 150 ++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index cfa2b4e678..ce69563960 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -913,7 +913,7 @@ void ScreenEdit::Update( float fDeltaTime ) { RageTimer tm; const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm ); - GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_Timing, tm ); + GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm ); } if( m_EditState == STATE_RECORDING ) @@ -931,7 +931,7 @@ void ScreenEdit::Update( float fDeltaTime ) continue; float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld; - float fStartBeat = max( fStartPlayingAtBeat, m_pSong->GetBeatFromElapsedTime(fStartedHoldingSeconds) ); + float fStartBeat = max( fStartPlayingAtBeat, m_pSong->m_SongTiming.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); float fEndBeat = max( fStartBeat, GAMESTATE->m_fSongBeat ); fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) ); @@ -976,11 +976,11 @@ void ScreenEdit::Update( float fDeltaTime ) float fLastBeat = NoteRowToBeat(m_iStopPlayingAt); if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING ) { - float fSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( fLastBeat ); - fLastBeat = m_pSong->m_Timing.GetBeatFromElapsedTime( fSeconds + 0.5f ); + float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( fLastBeat ); + fLastBeat = m_pSong->m_SongTiming.GetBeatFromElapsedTime( fSeconds + 0.5f ); } - float fStopAtSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; + float fStopAtSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; if( GAMESTATE->m_fMusicSeconds > fStopAtSeconds ) { // loop @@ -1071,7 +1071,7 @@ void ScreenEdit::UpdateTextInfo() RString sText; sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat ); - sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ); + sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ); switch( EDIT_MODE.GetValue() ) { DEFAULT_FAIL( EDIT_MODE.GetValue() ); @@ -1129,7 +1129,7 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Home: break; case EditMode_Full: - sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSong->m_Timing.m_fBeat0OffsetInSeconds ); + sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds ); sText += ssprintf( PREVIEW_START_FORMAT.GetValue(), PREVIEW_START.GetValue().c_str(), m_pSong->m_fMusicSampleStartSeconds ); sText += ssprintf( PREVIEW_LENGTH_FORMAT.GetValue(), PREVIEW_LENGTH.GetValue().c_str(), m_pSong->m_fMusicSampleLengthSeconds ); break; @@ -1243,7 +1243,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) m_iShiftAnchor = -1; return; } - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; switch( EditB ) { @@ -1443,13 +1443,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_LABEL_NEXT: { - ScrollTo( GAMESTATE->m_pCurSong->m_Timing. + ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); } break; case EDIT_BUTTON_LABEL_PREV: { - ScrollTo( GAMESTATE->m_pCurSong->m_Timing. + ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); } break; @@ -1579,7 +1579,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_BPM_UP: case EDIT_BUTTON_BPM_DOWN: { - float fBPM = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat ); + float fBPM = m_pSong->m_SongTiming.GetBPMAtBeat( GAMESTATE->m_fSongBeat ); float fDelta; switch( EditB ) { @@ -1600,7 +1600,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } float fNewBPM = fBPM + fDelta; - m_pSong->SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM ); + m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM ); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1627,24 +1627,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_Timing.m_StopSegments.size(); i++ ) + for( i=0; im_SongTiming.m_StopSegments.size(); i++ ) { - if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } - if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no StopSegment at the current beat + if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no StopSegment at the current beat { // create a new StopSegment if( fDelta > 0 ) - m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) ); + m_pSong->m_SongTiming.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) ); } - else // StopSegment being modified is m_Timing.m_StopSegments[i] + else // StopSegment being modified is m_SongTiming.m_StopSegments[i] { - m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i, - m_pSong->m_Timing.m_StopSegments.begin()+i+1); + m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta; + if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 ) + m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i, + m_pSong->m_SongTiming.m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1673,24 +1673,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_Timing.m_StopSegments.size(); i++ ) + for( i=0; im_SongTiming.m_StopSegments.size(); i++ ) { - if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } - if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no delay segment at the current beat + if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no delay segment at the current beat { // create a new delay segment if( fDelta > 0 ) m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta, true) ); } - else // delay segment being modified is m_Timing.m_StopSegments[i] + else // delay segment being modified is m_SongTiming.m_StopSegments[i] { - m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i, - m_pSong->m_Timing.m_StopSegments.begin()+i+1); + m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta; + if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 ) + m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i, + m_pSong->m_SongTiming.m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1718,7 +1718,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) else fDelta *= 40; } - m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fDelta; + m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta; (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1900,7 +1900,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( pCourse == NULL ) break; CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; - float fStartTime = m_pSong->GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + float fStartTime = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); int iAttack = FindAttackAtTime( ce.attacks, fStartTime ); if( iAttack >= 0 ) @@ -1941,7 +1941,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } else { - fStart = m_pSong->GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); + fStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); int iAttack = FindAttackAtTime( ce.attacks, fStart ); if( iAttack >= 0 ) @@ -1950,7 +1950,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( m_NoteFieldEdit.m_iEndMarker == -1 ) fEnd = m_pSong->m_fMusicLengthSeconds; else - fEnd = m_pSong->GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); + fEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); } g_fLastInsertAttackPositionSeconds = fStart; g_fLastInsertAttackDurationSeconds = fEnd - fStart; @@ -2265,7 +2265,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB ) fOffsetDelta *= 40; } - m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta; + m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fOffsetDelta; } break; } @@ -2381,8 +2381,8 @@ void ScreenEdit::TransitionEditState( EditState em ) AdjustSync::ResetOriginalSyncData(); /* Give a 1 second lead-in. If we're loading Player, this must be done first. */ - float fSeconds = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; - GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_Timing ); + float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; + GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_SongTiming ); GAMESTATE->m_bGameplayLeadIn.Set( false ); @@ -2463,7 +2463,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_PLAYING: case STATE_RECORDING: - const float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); + const float fStartSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); LOG->Trace( "Starting playback at %f", fStartSeconds ); RageSoundParams p; @@ -2627,21 +2627,21 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fBPM > 0 ) - m_pSong->SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM ); + m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop ); + m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true ); + m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2649,7 +2649,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = atoi( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - m_pSong->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); + m_pSong->m_SongTiming.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); } SetDirty( true ); } @@ -2658,7 +2658,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = atoi( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - m_pSong->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); + m_pSong->m_SongTiming.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); } SetDirty( true ); } @@ -2667,7 +2667,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - m_pSong->m_Timing.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); + m_pSong->m_SongTiming.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); } SetDirty( true ); } @@ -2676,25 +2676,25 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - m_pSong->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); + m_pSong->m_SongTiming.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); } SetDirty( true ); } else if ( SM == SM_BackFromLabelChange ) { RString sLabel = ScreenTextEntry::s_sLastAnswer; - if ( !m_pSong->m_Timing.DoesLabelExist(sLabel) ) + if ( !m_pSong->m_SongTiming.DoesLabelExist(sLabel) ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - m_pSong->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); + m_pSong->m_SongTiming.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - m_pSong->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); + m_pSong->m_SongTiming.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -2767,7 +2767,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; int iAttack; - g_fLastInsertAttackPositionSeconds = m_pSong->GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + g_fLastInsertAttackPositionSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] ); iAttack = FindAttackAtTime( ce.attacks, g_fLastInsertAttackPositionSeconds ); @@ -3024,7 +3024,7 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); + GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } static void ChangeLastBeatHint( const RString &sNew ) @@ -3242,7 +3242,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit ); g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit ); g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit ); - g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds) ); + g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds) ); g_SongInformation.rows[last_beat_hint].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedLastBeat) ); g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds) ); g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds) ); @@ -3256,9 +3256,9 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns case edit_timing_data: { const Song* pSong = GAMESTATE->m_pCurSong; - TimingData pTime = pSong->m_Timing; + TimingData pTime = pSong->m_SongTiming; const float fBeat = GAMESTATE->m_fSongBeat; - g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->GetBPMAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); @@ -3501,7 +3501,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex ); // scale timing data - m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); + m_pSong->m_SongTiming.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); // scale all other steps. const vector sIter = m_pSong->GetAllSteps(); @@ -3546,16 +3546,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_forward: - m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_backward: - m_pSong->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSong->m_SongTiming.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case convert_to_pause: { ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ); - float fMarkerStart = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); - float fMarkerEnd = m_pSong->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); + float fMarkerStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); + float fMarkerEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); // The length of the stop segment we're going to create. This includes time spent in any // stops in the selection, which will be deleted and subsumed into the new stop. @@ -3567,9 +3567,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns m_NoteFieldEdit.m_iBeginMarker + 1, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSong->m_Timing.DeleteRows( m_NoteFieldEdit.m_iBeginMarker, + m_pSong->m_SongTiming.DeleteRows( m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSong->m_Timing.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); + m_pSong->m_SongTiming.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); m_NoteFieldEdit.m_iBeginMarker = -1; m_NoteFieldEdit.m_iEndMarker = -1; break; @@ -3577,14 +3577,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_pause_to_beat: { // TODO: Convert both Delays and Stops at once. - float fStopSeconds = m_pSong->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ); - m_pSong->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 ); + float fStopSeconds = m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ); + m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 ); - float fStopBeats = fStopSeconds * m_pSong->GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60; + float fStopBeats = fStopSeconds * m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60; // don't move the step from where it is, just move everything later NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: @@ -3701,7 +3701,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec break; case beat_0_offset: ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, - ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds), 20, + ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds), 20, ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); break; case last_beat_hint: @@ -3750,7 +3750,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, - ssprintf( "%.4f", m_pSong->GetBPMAtBeat(GAMESTATE->m_fSongBeat) ), + ssprintf( "%.4f", m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) ), 10 ); break; @@ -3758,7 +3758,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromStopChange, ENTER_STOP_VALUE, - ssprintf( "%.4f", m_pSong->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; @@ -3766,7 +3766,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromDelayChange, ENTER_DELAY_VALUE, - ssprintf( "%.4f", m_pSong->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSong->m_SongTiming.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; @@ -3774,7 +3774,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureNumeratorChange, ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", m_pSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ), + ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ), 3 ); break; @@ -3782,7 +3782,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureDenominatorChange, ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", m_pSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ), + ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ), 3 ); break; @@ -3790,7 +3790,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTickcountChange, ENTER_TICKCOUNT_VALUE, - ssprintf( "%d", m_pSong->m_Timing.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSong->m_SongTiming.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ), 2 ); break; @@ -3798,7 +3798,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromComboChange, ENTER_COMBO_VALUE, - ssprintf( "%d", m_pSong->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSong->m_SongTiming.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), 4 ); break; @@ -3806,7 +3806,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromLabelChange, ENTER_LABEL_VALUE, - ssprintf( "%s", m_pSong->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), + ssprintf( "%s", m_pSong->m_SongTiming.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), 64 ); break; @@ -3814,7 +3814,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", m_pSong->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSong->m_SongTiming.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; @@ -4021,7 +4021,7 @@ void ScreenEdit::CheckNumberOfNotesAndUndo() if( EDIT_MODE.GetValue() != EditMode_Home ) return; - TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ); + TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ); int rowsPerMeasure = curTime.m_iDenominator * curTime.m_iNumerator; for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure ) @@ -4073,7 +4073,7 @@ float ScreenEdit::GetMaximumBeatForNewNote() const /* Round up to the next measure end. Some songs end on weird beats * mid-measure, and it's odd to have movement capped to these weird * beats. */ - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; fEndBeat += beatsPerMeasure; fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure ); From 44ee6fc0de51f2bc8a75e44e9228f2803fd50d10 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 21:19:40 -0400 Subject: [PATCH 029/333] [splittiming] Simplify. --- src/NoteField.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 213d5e1e09..20e7c08f8b 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -785,8 +785,10 @@ void NoteField::DrawPrimitives() { ASSERT(GAMESTATE->m_pCurSong); + const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; + // BPM text - FOREACH_CONST( BPMSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments, seg ) + FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -797,7 +799,7 @@ void NoteField::DrawPrimitives() } // Freeze text - FOREACH_CONST( StopSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments, seg ) + FOREACH_CONST( StopSegment, timing.m_StopSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -808,7 +810,7 @@ void NoteField::DrawPrimitives() } // Warp text - FOREACH_CONST( WarpSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_WarpSegments, seg ) + FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -819,7 +821,7 @@ void NoteField::DrawPrimitives() } // Time Signature text - FOREACH_CONST( TimeSignatureSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_vTimeSignatureSegments, seg ) + FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -830,7 +832,7 @@ void NoteField::DrawPrimitives() } // Tickcount text - FOREACH_CONST( TickcountSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_TickcountSegments, seg ) + FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -841,7 +843,7 @@ void NoteField::DrawPrimitives() } // Combo text - FOREACH_CONST( ComboSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_ComboSegments, seg ) + FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -852,7 +854,7 @@ void NoteField::DrawPrimitives() } // Label text - FOREACH_CONST( LabelSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_LabelSegments, seg ) + FOREACH_CONST( LabelSegment, timing.m_LabelSegments, seg ) { if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) { @@ -872,7 +874,7 @@ void NoteField::DrawPrimitives() FOREACH_CONST( Attack, ce.attacks, a ) { float fSecond = a->fStartSecond; - float fBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fSecond ); + float fBeat = timing.GetBeatFromElapsedTime( fSecond ); if( BeatToNoteRow(fBeat) >= iFirstRowToDraw && BeatToNoteRow(fBeat) <= iLastRowToDraw) From f629f06c34a84806360ae8f0c26a3e2e4d500ee0 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 22:42:46 -0400 Subject: [PATCH 030/333] [splittiming] Abstract functionality for later. I don't want to repeat code for Steps. --- src/NotesLoaderSM.cpp | 476 +++++++++++++++++++++-------------------- src/NotesLoaderSM.h | 7 + src/NotesLoaderSSC.cpp | 319 ++++++++------------------- src/NotesLoaderSSC.h | 5 + 4 files changed, 343 insertions(+), 464 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 3ee9994332..3fa6432713 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -103,6 +103,244 @@ bool SMLoader::LoadTimingFromFile( const RString &fn, TimingData &out ) return true; } +void SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) +{ + vector arrayBPMChangeExpressions; + split( sParam, ",", arrayBPMChangeExpressions ); + + // prepare storage variables for negative BPMs -> Warps. + float negBeat = -1; + float negBPM = 1; + float highspeedBeat = -1; + + for( unsigned b=0; b arrayBPMChangeValues; + split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); + // XXX: Hard to tell which file caused this. + if( arrayBPMChangeValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #BPMs value \"%s\" (must have exactly one '='), ignored.", + arrayBPMChangeExpressions[b].c_str() ); + continue; + } + + const float fBeat = StringToFloat( arrayBPMChangeValues[0] ); + const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); + + if( fNewBPM < 0.0f ) + { + out.m_bHasNegativeBpms = true; + negBeat = fBeat; + negBPM = fNewBPM; + } + else if( fNewBPM > 0.0f ) + { + // add in a warp. + if( negBPM < 0 ) + { + float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); + WarpSegment new_seg(negBeat, endBeat); + out.AddWarpSegment( new_seg ); + + negBeat = -1; + negBPM = 1; + } + // too fast. make it a warp. + if( fNewBPM > FAST_BPM_WARP ) + { + highspeedBeat = fBeat; + } + else + { + // add in a warp. + if( highspeedBeat > 0 ) + { + WarpSegment new_seg(highspeedBeat, fBeat); + out.AddWarpSegment( new_seg ); + highspeedBeat = -1; + } + { + BPMSegment new_seg; + new_seg.m_iStartRow = BeatToNoteRow(fBeat); + new_seg.SetBPM( fNewBPM ); + out.AddBPMSegment( new_seg ); + } + } + } + } +} + +void SMLoader::ProcessStops( TimingData &out, const RString sParam ) +{ + vector arrayFreezeExpressions; + split( sParam, ",", arrayFreezeExpressions ); + + // Prepare variables for negative stop conversion. + float negBeat = -1; + float negPause = 0; + + for( unsigned f=0; f arrayFreezeValues; + split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); + if( arrayFreezeValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #STOPS value \"%s\" (must have exactly one '='), ignored.", + arrayFreezeExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); + const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); + + // Process the prior stop. + if( negPause > 0 ) + { + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + if( negBeat + fSkipBeats > fFreezeBeat ) + fSkipBeats = fFreezeBeat - negBeat; + + WarpSegment ws( negBeat, negBeat + fSkipBeats); + out.AddWarpSegment( ws ); + + negBeat = -1; + negPause = 0; + } + + if( fFreezeSeconds < 0.0f ) + { + negBeat = fFreezeBeat; + negPause = -fFreezeSeconds; + } + else if( fFreezeSeconds > 0.0f ) + { + StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); + out.AddStopSegment( ss ); + } + + } + + // Process the prior stop if there was one. + if( negPause > 0 ) + { + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + WarpSegment ws( negBeat, negBeat + fSkipBeats); + out.AddWarpSegment( ws ); + } +} + +void SMLoader::ProcessDelays( TimingData &out, const RString sParam ) +{ + vector arrayDelayExpressions; + split( sParam, ",", arrayDelayExpressions ); + + for( unsigned f=0; f arrayDelayValues; + split( arrayDelayExpressions[f], "=", arrayDelayValues ); + if( arrayDelayValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #DELAYS value \"%s\" (must have exactly one '='), ignored.", + arrayDelayExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = StringToFloat( arrayDelayValues[0] ); + const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); + + StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); + // XXX: Remove Negatives Bug? + new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); + new_seg.m_fStopSeconds = fFreezeSeconds; + + // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + + if(fFreezeSeconds > 0.0f) + out.AddStopSegment( new_seg ); + else + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); + } +} + +void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam ) +{ + vector vs1; + split( sParam, ",", vs1 ); + + FOREACH_CONST( RString, vs1, s1 ) + { + vector vs2; + split( *s1, "=", vs2 ); + + if( vs2.size() < 3 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() ); + continue; + } + + const float fBeat = StringToFloat( vs2[0] ); + + TimeSignatureSegment seg; + seg.m_iStartRow = BeatToNoteRow(fBeat); + seg.m_iNumerator = atoi( vs2[1] ); + seg.m_iDenominator = atoi( vs2[2] ); + + if( fBeat < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat ); + continue; + } + + if( seg.m_iNumerator < 1 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator ); + continue; + } + + if( seg.m_iDenominator < 1 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator ); + continue; + } + + out.AddTimeSignatureSegment( seg ); + } +} + +void SMLoader::ProcessTickcounts( TimingData &out, const RString sParam ) +{ + vector arrayTickcountExpressions; + split( sParam, ",", arrayTickcountExpressions ); + + for( unsigned f=0; f arrayTickcountValues; + split( arrayTickcountExpressions[f], "=", arrayTickcountValues ); + if( arrayTickcountValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #TICKCOUNTS value \"%s\" (must have exactly one '='), ignored.", + arrayTickcountExpressions[f].c_str() ); + continue; + } + + const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); + int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT); + + TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks ); + out.AddTickcountSegment( new_seg ); + } +} + void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) { out.m_fBeat0OffsetInSeconds = 0; @@ -123,255 +361,27 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } else if( sValueName=="BPMS" ) { - vector arrayBPMChangeExpressions; - split( sParams[1], ",", arrayBPMChangeExpressions ); - - // prepare storage variables for negative BPMs -> Warps. - float negBeat = -1; - float negBPM = 1; - float highspeedBeat = -1; - - for( unsigned b=0; b arrayBPMChangeValues; - split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); - // XXX: Hard to tell which file caused this. - if( arrayBPMChangeValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() ); - continue; - } - - const float fBeat = StringToFloat( arrayBPMChangeValues[0] ); - const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); - - if( fNewBPM < 0.0f ) - { - out.m_bHasNegativeBpms = true; - negBeat = fBeat; - negBPM = fNewBPM; - } - else if( fNewBPM > 0.0f ) - { - // add in a warp. - if( negBPM < 0 ) - { - float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); - WarpSegment new_seg(negBeat, endBeat); - out.AddWarpSegment( new_seg ); - - negBeat = -1; - negBPM = 1; - } - // too fast. make it a warp. - if( fNewBPM > FAST_BPM_WARP ) - { - highspeedBeat = fBeat; - } - else - { - // add in a warp. - if( highspeedBeat > 0 ) - { - WarpSegment new_seg(highspeedBeat, fBeat); - out.AddWarpSegment( new_seg ); - highspeedBeat = -1; - } - { - BPMSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(fBeat); - new_seg.SetBPM( fNewBPM ); - out.AddBPMSegment( new_seg ); - } - } - } - } + ProcessBPMs(out, sParams[1]); } else if( sValueName=="STOPS" || sValueName=="FREEZES" ) { - vector arrayFreezeExpressions; - split( sParams[1], ",", arrayFreezeExpressions ); - - // Prepare variables for negative stop conversion. - float negBeat = -1; - float negPause = 0; - - for( unsigned f=0; f arrayFreezeValues; - split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); - if( arrayFreezeValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayFreezeExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); - - // Process the prior stop. - if( negPause > 0 ) - { - BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); - float fSecondsPerBeat = 60 / oldBPM.GetBPM(); - float fSkipBeats = negPause / fSecondsPerBeat; - - if( negBeat + fSkipBeats > fFreezeBeat ) - fSkipBeats = fFreezeBeat - negBeat; - - WarpSegment ws( negBeat, negBeat + fSkipBeats); - out.AddWarpSegment( ws ); - - negBeat = -1; - negPause = 0; - } - - if( fFreezeSeconds < 0.0f ) - { - negBeat = fFreezeBeat; - negPause = -fFreezeSeconds; - } - else if( fFreezeSeconds > 0.0f ) - { - StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); - out.AddStopSegment( ss ); - } - - } - - // Process the prior stop if there was one. - if( negPause > 0 ) - { - BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); - float fSecondsPerBeat = 60 / oldBPM.GetBPM(); - float fSkipBeats = negPause / fSecondsPerBeat; - - WarpSegment ws( negBeat, negBeat + fSkipBeats); - out.AddWarpSegment( ws ); - } + ProcessStops(out, sParams[1]); } else if( sValueName=="DELAYS" ) { - vector arrayDelayExpressions; - split( sParams[1], ",", arrayDelayExpressions ); - - for( unsigned f=0; f arrayDelayValues; - split( arrayDelayExpressions[f], "=", arrayDelayValues ); - if( arrayDelayValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayDelayExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayDelayValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); - - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); - // XXX: Remove Negatives Bug? - new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); - new_seg.m_fStopSeconds = fFreezeSeconds; - - // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - - if(fFreezeSeconds > 0.0f) - out.AddStopSegment( new_seg ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } + ProcessDelays(out, sParams[1]); } else if( sValueName=="TIMESIGNATURES" ) { - vector vs1; - split( sParams[1], ",", vs1 ); - - FOREACH_CONST( RString, vs1, s1 ) - { - vector vs2; - split( *s1, "=", vs2 ); - - if( vs2.size() < 3 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() ); - continue; - } - - const float fBeat = StringToFloat( vs2[0] ); - - TimeSignatureSegment seg; - seg.m_iStartRow = BeatToNoteRow(fBeat); - seg.m_iNumerator = atoi( vs2[1] ); - seg.m_iDenominator = atoi( vs2[2] ); - - if( fBeat < 0 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat ); - continue; - } - - if( seg.m_iNumerator < 1 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator ); - continue; - } - - if( seg.m_iDenominator < 1 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator ); - continue; - } - - out.AddTimeSignatureSegment( seg ); - } + ProcessTimeSignatures(out, sParams[1]); } else if( sValueName=="TICKCOUNTS" ) { - vector arrayTickcountExpressions; - split( sParams[1], ",", arrayTickcountExpressions ); - - for( unsigned f=0; f arrayTickcountValues; - split( arrayTickcountExpressions[f], "=", arrayTickcountValues ); - if( arrayTickcountValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayTickcountExpressions[f].c_str() ); - continue; - } - - const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); - int iTicks = atoi( arrayTickcountValues[1] ); - // you're lazy, let SM do the work for you... -DaisuMaster - if( iTicks < 1) iTicks = 1; - if( iTicks > ROWS_PER_BEAT ) iTicks = ROWS_PER_BEAT; - - TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks ); - out.AddTickcountSegment( new_seg ); - - if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants - { - // LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks ); - //out.AddTickcountSegment( new_seg ); - } - else - { - //LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks ); - //LOG->UserLog( "Song file", "(UNKNOWN)", "Clamping tickcount value to %d at beat %f.", iTicks, fTickcountBeat); - //etc - } - } + ProcessTickcounts(out, sParams[1]); } // Ensure all of the warps are handled right. sort(out.m_WarpSegments.begin(), out.m_WarpSegments.end()); diff --git a/src/NotesLoaderSM.h b/src/NotesLoaderSM.h index db1e938528..d61c7b19ff 100644 --- a/src/NotesLoaderSM.h +++ b/src/NotesLoaderSM.h @@ -25,6 +25,13 @@ namespace SMLoader bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot ); bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong ); bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression ); + + + void ProcessBPMs( TimingData &, const RString ); + void ProcessStops( TimingData &, const RString ); + void ProcessDelays( TimingData &, const RString ); + void ProcessTimeSignatures( TimingData &, const RString ); + void ProcessTickcounts( TimingData &, const RString ); } #endif diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index b242781117..51c8b83f66 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -112,6 +112,86 @@ bool SSCLoader::LoadFromDir( const RString &sPath, Song &out ) return LoadFromSSCFile( sPath + aFileNames[0], out ); } +void SSCLoader::ProcessWarps( TimingData &out, const RString sParam ) +{ + vector arrayWarpExpressions; + split( sParam, ",", arrayWarpExpressions ); + + for( unsigned b=0; b arrayWarpValues; + split( arrayWarpExpressions[b], "=", arrayWarpValues ); + // XXX: Hard to tell which file caused this. + if( arrayWarpValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #WARPS value \"%s\" (must have exactly one '='), ignored.", + arrayWarpExpressions[b].c_str() ); + continue; + } + + const float fBeat = StringToFloat( arrayWarpValues[0] ); + const float fNewBeat = StringToFloat( arrayWarpValues[1] ); + + if(fNewBeat > fBeat) + out.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); + else + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat ); + } + } +} + +void SSCLoader::ProcessLabels( TimingData &out, const RString sParam ) +{ + vector arrayLabelExpressions; + split( sParam, ",", arrayLabelExpressions ); + + for( unsigned b=0; b arrayLabelValues; + split( arrayLabelExpressions[b], "=", arrayLabelValues ); + if( arrayLabelValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #LABELS value \"%s\" (must have exactly one '='), ignored.", + arrayLabelExpressions[b].c_str() ); + continue; + } + + const float fBeat = StringToFloat( arrayLabelValues[0] ); + RString sLabel = arrayLabelValues[1]; + TrimRight(sLabel); + if( fBeat >= 0.0f ) + out.AddLabelSegment( LabelSegment(fBeat, sLabel) ); + else + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() ); + } + + } +} + +void SSCLoader::ProcessCombos( TimingData &out, const RString sParam ) +{ + vector arrayComboExpressions; + split( sParam, ",", arrayComboExpressions ); + + for( unsigned f=0; f arrayComboValues; + split( arrayComboExpressions[f], "=", arrayComboValues ); + if( arrayComboValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #COMBOS value \"%s\" (must have exactly one '='), ignored.", + arrayComboExpressions[f].c_str() ); + continue; + } + const float fComboBeat = StringToFloat( arrayComboValues[0] ); + const int iCombos = atoi( arrayComboValues[1] ); + ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); + out.AddComboSegment( new_seg ); + } +} + bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache ) { LOG->Trace( "Song::LoadFromSSCFile(%s)", sPath.c_str() ); @@ -390,264 +470,41 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach * if the steps do not have their own timing. */ else if( sValueName=="STOPS" ) { - vector arrayFreezeExpressions; - split( sParams[1], ",", arrayFreezeExpressions ); - - for( unsigned f=0; f arrayFreezeValues; - split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); - if( arrayFreezeValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayFreezeExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); - - if(fFreezeSeconds > 0.0f) - { - // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.m_SongTiming.AddStopSegment( new_seg ); - } - else - { - // negative stops (hi JS!) -aj - if( PREFSMAN->m_bQuirksMode ) - { - // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.m_SongTiming.AddStopSegment( new_seg ); - } - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } - } + SMLoader::ProcessStops(out.m_SongTiming, sParams[1]); } else if( sValueName=="DELAYS" ) { - vector arrayDelayExpressions; - split( sParams[1], ",", arrayDelayExpressions ); - - for( unsigned f=0; f arrayDelayValues; - split( arrayDelayExpressions[f], "=", arrayDelayValues ); - if( arrayDelayValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayDelayExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayDelayValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); - - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); - - // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - - if(fFreezeSeconds > 0.0f) - out.m_SongTiming.AddStopSegment( new_seg ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } + SMLoader::ProcessDelays(out.m_SongTiming, sParams[1]); } else if( sValueName=="BPMS" ) { - vector arrayBPMChangeExpressions; - split( sParams[1], ",", arrayBPMChangeExpressions ); - - for( unsigned b=0; b arrayBPMChangeValues; - split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); - // XXX: Hard to tell which file caused this. - if( arrayBPMChangeValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() ); - continue; - } - - const float fBeat = StringToFloat( arrayBPMChangeValues[0] ); - const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); - - if(fNewBPM > 0.0f) - out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); - else - { - out.m_SongTiming.m_bHasNegativeBpms = true; - // only add Negative BPMs in quirks mode -aj - if( PREFSMAN->m_bQuirksMode ) - out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM ); - } - } + SMLoader::ProcessBPMs(out.m_SongTiming, sParams[1]); } else if( sValueName=="WARPS" ) { - vector arrayWarpExpressions; - split( sParams[1], ",", arrayWarpExpressions ); - - for( unsigned b=0; b arrayWarpValues; - split( arrayWarpExpressions[b], "=", arrayWarpValues ); - // XXX: Hard to tell which file caused this. - if( arrayWarpValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayWarpExpressions[b].c_str() ); - continue; - } - - const float fBeat = StringToFloat( arrayWarpValues[0] ); - const float fNewBeat = StringToFloat( arrayWarpValues[1] ); - - if(fNewBeat > fBeat) - out.m_SongTiming.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); - else - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat ); - } - } + ProcessWarps( out.m_SongTiming, sParams[1] ); } else if( sValueName=="LABELS" ) { - vector arrayLabelExpressions; - split( sParams[1], ",", arrayLabelExpressions ); - - for( unsigned b=0; b arrayLabelValues; - split( arrayLabelExpressions[b], "=", arrayLabelValues ); - if( arrayLabelValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayLabelExpressions[b].c_str() ); - continue; - } - - const float fBeat = StringToFloat( arrayLabelValues[0] ); - RString sLabel = arrayLabelValues[1]; - TrimRight(sLabel); - if( fBeat >= 0.0f ) - out.m_SongTiming.AddLabelSegment( LabelSegment(fBeat, sLabel) ); - else - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() ); - } - - } + ProcessLabels( out.m_SongTiming, sParams[1] ); } else if( sValueName=="TIMESIGNATURES" ) { - vector vs1; - split( sParams[1], ",", vs1 ); - - FOREACH_CONST( RString, vs1, s1 ) - { - vector vs2; - split( *s1, "=", vs2 ); - - if( vs2.size() < 3 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() ); - continue; - } - - const float fBeat = StringToFloat( vs2[0] ); - - TimeSignatureSegment seg; - seg.m_iStartRow = BeatToNoteRow(fBeat); - seg.m_iNumerator = atoi( vs2[1] ); - seg.m_iDenominator = atoi( vs2[2] ); - - if( fBeat < 0 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat ); - continue; - } - - if( seg.m_iNumerator < 1 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator ); - continue; - } - - if( seg.m_iDenominator < 1 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator ); - continue; - } - - out.m_SongTiming.AddTimeSignatureSegment( seg ); - } + SMLoader::ProcessTimeSignatures(out.m_SongTiming, sParams[1]); } else if( sValueName=="TICKCOUNTS" ) { - vector arrayTickcountExpressions; - split( sParams[1], ",", arrayTickcountExpressions ); - - for( unsigned f=0; f arrayTickcountValues; - split( arrayTickcountExpressions[f], "=", arrayTickcountValues ); - if( arrayTickcountValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayTickcountExpressions[f].c_str() ); - continue; - } - - const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); - const int iTicks = atoi( arrayTickcountValues[1] ); - TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks ); - - if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants - { - // LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks ); - out.m_SongTiming.AddTickcountSegment( new_seg ); - } - else - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks ); - } - } + SMLoader::ProcessTickcounts(out.m_SongTiming, sParams[1]); } else if( sValueName=="COMBOS" ) { - vector arrayComboExpressions; - split( sParams[1], ",", arrayComboExpressions ); - - for( unsigned f=0; f arrayComboValues; - split( arrayComboExpressions[f], "=", arrayComboValues ); - if( arrayComboValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayComboExpressions[f].c_str() ); - continue; - } - const float fComboBeat = StringToFloat( arrayComboValues[0] ); - const int iCombos = atoi( arrayComboValues[1] ); - ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); - out.m_SongTiming.AddComboSegment( new_seg ); - } + ProcessCombos( out.m_SongTiming, sParams[1] ); } /* The following are cache tags. Never fill their values diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index ff44a23cb5..53c9d5c72b 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -75,6 +75,11 @@ namespace SSCLoader * @param bFromCache a flag to determine if this song is loaded from a cache file. */ void TidyUpData( Song &song, bool bFromCache ); + + + void ProcessWarps( TimingData &, const RString ); + void ProcessLabels( TimingData &, const RString ); + void ProcessCombos( TimingData &, const RString ); } #endif /** From 2ad3b729f1fefb45cbe4f98eab113eeeccb244ac Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 22:49:47 -0400 Subject: [PATCH 031/333] [splittiming] Define far ahead version. This will let other branches develop .ssc if needed while this branch takes its time. --- Docs/Changelog_SSCformat.txt | 3 +++ src/NotesLoaderSSC.h | 2 ++ src/Song.h | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index 95b48cf7d7..fb04d68912 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -9,6 +9,9 @@ change to JSON, but it is unsure if this will be done. Implement .ssc at your own risk. ________________________________________________________________________________ +[v0.7] - theDtTvB, Wolfman2000 +* Split Timing officially implemented. + [v0.59] - Wolfman2000 * Typo fix: #RADARVALUES needed a semicolon at the end, not a colon. diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index 53c9d5c72b..bf85bdd73c 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -25,6 +25,8 @@ enum SSCLoadingStates const float VERSION_RADAR_FAKE = 0.53f; /** @brief The version where WarpSegments started to be utilized. */ const float VERSION_WARP_SEGMENT = 0.56f; +/** @brief The version that formally introduced Split Timing. */ +const float VERSION_SPLIT_TIMING = 0.7f; /** * @brief The SSCLoader handles all of the parsing needed for .ssc files. diff --git a/src/Song.h b/src/Song.h index 1d49724795..ac41bf476c 100644 --- a/src/Song.h +++ b/src/Song.h @@ -17,7 +17,7 @@ struct lua_State; struct BackgroundChange; /** @brief The version of the .ssc file format. */ -const static float STEPFILE_VERSION_NUMBER = 0.59f; +const static float STEPFILE_VERSION_NUMBER = 0.7f; /** @brief How many edits for this song can each profile have? */ const int MAX_EDITS_PER_SONG_PER_PROFILE = 5; From 1ea093cd5f757073361158f66faedc5b290344e6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 23:16:56 -0400 Subject: [PATCH 032/333] [splittiming] Cleanup, more prepwork. --- src/NotesLoaderSSC.cpp | 178 +++++------------------------------------ src/TimingData.cpp | 12 ++- src/TimingData.h | 4 + 3 files changed, 34 insertions(+), 160 deletions(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 51c8b83f66..8af0e084ea 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -4,7 +4,7 @@ #include "GameManager.h" #include "MsdFile.h" // No JSON here. #include "NoteTypes.h" -#include "NotesLoaderSM.h" // For loading SM style edits. +#include "NotesLoaderSM.h" // For programming shortcuts. #include "RageFileManager.h" #include "RageLog.h" #include "RageUtil.h" @@ -30,70 +30,7 @@ const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60 KB */ bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGChangeExpression ) { - vector aBGChangeValues; - split( sBGChangeExpression, "=", aBGChangeValues, false ); - - aBGChangeValues.resize( min((int)aBGChangeValues.size(),11) ); - - switch( aBGChangeValues.size() ) - { - case 11: - change.m_def.m_sColor2 = aBGChangeValues[10]; - change.m_def.m_sColor2.Replace( '^', ',' ); - change.m_def.m_sColor2 = RageColor::NormalizeColorString( change.m_def.m_sColor2 ); - // fall through - case 10: - change.m_def.m_sColor1 = aBGChangeValues[9]; - change.m_def.m_sColor1.Replace( '^', ',' ); - change.m_def.m_sColor1 = RageColor::NormalizeColorString( change.m_def.m_sColor1 ); - // fall through - case 9: - change.m_sTransition = aBGChangeValues[8]; - // fall through - case 8: - change.m_def.m_sFile2 = aBGChangeValues[7]; - // fall through - case 7: - change.m_def.m_sEffect = aBGChangeValues[6]; - // fall through - case 6: - // param 7 overrides this. - // Backward compatibility: - if( change.m_def.m_sEffect.empty() ) - { - bool bLoop = atoi( aBGChangeValues[5] ) != 0; - if( !bLoop ) - change.m_def.m_sEffect = SBE_StretchNoLoop; - } - // fall through - case 5: - // param 7 overrides this. - // Backward compatibility: - if( change.m_def.m_sEffect.empty() ) - { - bool bRewindMovie = atoi( aBGChangeValues[4] ) != 0; - if( bRewindMovie ) - change.m_def.m_sEffect = SBE_StretchRewind; - } - // fall through - case 4: - // param 9 overrides this. - // Backward compatibility: - if( change.m_sTransition.empty() ) - change.m_sTransition = (atoi( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; - // fall through - case 3: - change.m_fRate = StringToFloat( aBGChangeValues[2] ); - // fall through - case 2: - change.m_def.m_sFile1 = aBGChangeValues[1]; - // fall through - case 1: - change.m_fStartBeat = StringToFloat( aBGChangeValues[0] ); - // fall through - } - - return aBGChangeValues.size() >= 2; + return SMLoader::LoadFromBGChangesString( change, sBGChangeExpression ); } bool SSCLoader::LoadFromDir( const RString &sPath, Song &out ) @@ -613,41 +550,14 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach out.AddSteps( pNewNotes ); } - else if( sValueName=="BPMS" ) + else if( sValueName=="BPMS" ) // This must ALWAYS be here in Split Timing. { - /* state = GETTING_STEP_TIMING_INFO; - vector arrayBPMChangeExpressions; - split( sParams[1], ",", arrayBPMChangeExpressions ); - - for( unsigned b=0; b arrayBPMChangeValues; - split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); - // XXX: Hard to tell which file caused this. - if( arrayBPMChangeValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() ); - continue; - } - - const float fBeat = StringToFloat( arrayBPMChangeValues[0] ); - const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); - - if(fNewBPM > 0.0f) - pNewNotes->m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); - else - { - pNewNotes->m_Timing.m_bHasNegativeBpms = true; - // only add Negative BPMs in quirks mode -aj - if( PREFSMAN->m_bQuirksMode ) - pNewNotes->m_Timing.AddBPMSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM ); - } - } - */ + /* + pNewNotes->m_Timing = TimingData(out.m_SongTiming.m_fBeat0OffsetInSeconds); + SMLoader::ProcessBPMs(pNewNotes->m_Timing, sParams[1]); + */ + } break; } @@ -655,28 +565,31 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach { if( sValueName=="STOPS" ) { - // copy from above when it's time. + // SMLoader::ProcessStops(pNewNotes->m_Timing, sParams[1]); } else if( sValueName=="DELAYS" ) { - // copy from above when it's time. + // SMLoader::ProcessDelays(pNewNotes->m_Timing, sParams[1]); } else if( sValueName=="TIMESIGNATURES" ) { - // copy from above when it's time. + // SMLoader::ProcessTimeSignatures(pNewNotes->m_Timing, sParams[1]); } - else if( sValueName=="TICKCOUNTS" ) { - // copy from above when it's time. + // SMLoader::ProcessTickcounts(pNewNotes->m_Timing, sParams[1]); } else if( sValueName=="COMBOS" ) { - // copy from above when it's time. + // ProcessCombos(pNewNotes->m_Timing, sParams[1]); } - else if( sValueName=="WARPS" || sValueName=="LABELS" ) + else if( sValueName=="WARPS" ) { - // copy from above when it's time. + // ProcessWarps(pNewNotes->m_Timing, sParams[1]); + } + else if( sValueName=="LABELS" ) + { + // ProcessLabels(pNewNotes->m_Timing, sParams[1]); } else if( sValueName=="ATTACKS" ) { @@ -731,10 +644,9 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach */ } - else if( sValueName=="NOTES" ) + else if( sValueName=="NOTES" || sValueName=="NOTES2" ) { state = GETTING_SONG_INFO; - // pNewNotes->m_Timing.m_fBeat0OffsetInSeconds = out.m_Timing.m_fBeat0OffsetInSeconds; pNewNotes->SetSMNoteData( sParams[1] ); pNewNotes->TidyUpData(); out.AddSteps( pNewNotes ); @@ -952,55 +864,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat void SSCLoader::TidyUpData( Song &song, bool bFromCache ) { - /* - * Hack: if the song has any changes at all (so it won't use a random BGA) - * and doesn't end with "-nosongbg-", add a song background BGC. Remove - * "-nosongbg-" if it exists. - * - * This way, songs that were created earlier, when we added the song BG - * at the end by default, will still behave as expected; all new songs will - * have to add an explicit song BG tag if they want it. This is really a - * formatting hack only; nothing outside of SMLoader ever sees "-nosongbg-". - */ - vector &bg = song.GetBackgroundChanges(BACKGROUND_LAYER_1); - if( !bg.empty() ) - { - /* BGChanges have been sorted. On the odd chance that a BGChange exists - * with a very high beat, search the whole list. */ - bool bHasNoSongBgTag = false; - - for( unsigned i = 0; !bHasNoSongBgTag && i < bg.size(); ++i ) - { - if( !bg[i].m_def.m_sFile1.CompareNoCase(NO_SONG_BG_FILE) ) - { - bg.erase( bg.begin()+i ); - bHasNoSongBgTag = true; - } - } - - // If there's no -nosongbg- tag, add the song BG. - if( !bHasNoSongBgTag ) do - { - /* If we're loading cache, -nosongbg- should always be in there. We - * must not call IsAFile(song.GetBackgroundPath()) when loading cache. */ - if( bFromCache ) - break; - - /* If BGChanges already exist after the last beat, don't add the - * background in the middle. */ - if( !bg.empty() && bg.back().m_fStartBeat-0.0001f >= song.m_fLastBeat ) - break; - - // If the last BGA is already the song BGA, don't add a duplicate. - if( !bg.empty() && !bg.back().m_def.m_sFile1.CompareNoCase(song.m_sBackgroundFile) ) - break; - - if( !IsAFile( song.GetBackgroundPath() ) ) - break; - - bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) ); - } while(0); - } + SMLoader::TidyUpData(song, bFromCache); } /* diff --git a/src/TimingData.cpp b/src/TimingData.cpp index bb6911fad4..022976a349 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -8,10 +8,16 @@ #include -TimingData::TimingData() +TimingData::TimingData() : + m_fBeat0OffsetInSeconds(0), + m_bHasNegativeBpms(false) { - m_fBeat0OffsetInSeconds = 0; - m_bHasNegativeBpms = false; +} + +TimingData::TimingData(float fOffset) : + m_fBeat0OffsetInSeconds(fOffset), + m_bHasNegativeBpms(false) +{ } void TimingData::GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut ) const diff --git a/src/TimingData.h b/src/TimingData.h index 5464a8748e..36f1d33456 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -658,6 +658,10 @@ public: * @brief Sets up initial timing data. */ TimingData(); + /** + * @brief Sets up initial timing data with a defined offset. + * @param fOffset the offset from the 0th beat. */ + TimingData(float fOffset); /** * @brief Gets the actual BPM of the song. * @param fMinBPMOut the minimium specified BPM. From fab4cda5ff86d72417c0b166e4fde57485c03435 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 9 May 2011 23:35:21 -0400 Subject: [PATCH 033/333] [splittiming] Comment cleanup. --- src/NotesLoaderSSC.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 8af0e084ea..dde0d86e4a 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -21,9 +21,6 @@ const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60 KB /** * @brief Attempt to load any background changes in use by this song. - * - * This code is right now copied from NotesLoaderSM. There may be a time - * when we add to this code, or perhaps just refactor it properly. * @param change a reference to the background change. * @param sBGChangeExpression a reference to the list of changes to be made. * @return its success or failure. From 285f227851b31277a8637e9d21cd2c7721186891 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 13:27:35 +0700 Subject: [PATCH 034/333] [splittiming] tie Step's TimingData to player. --- src/Player.cpp | 39 +++++++++++++++++++++++++-------------- src/Player.h | 2 ++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index 2c793bb4c1..95353c1669 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -541,6 +541,8 @@ void Player::Load() if( GAMESTATE->m_pCurGame->m_bAllowHopos ) NoteDataUtil::SetHopoPossibleFlags( pSong, m_NoteData ); + m_Timing = &GAMESTATE->m_pCurSteps[pn]->m_Timing; + switch( GAMESTATE->m_PlayMode ) { case PLAY_MODE_RAVE: @@ -1528,7 +1530,7 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool // Is this the row we want? do { const TapNote &tn = begin->second; - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( begin->first ) ) + if( m_Timing->IsWarpAtRow( begin->first ) ) break; if( tn.type == TapNote::empty ) break; @@ -1579,7 +1581,7 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b ++iter; continue; } - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) ) + if( m_Timing->IsWarpAtRow( iter.Row() ) ) { ++iter; continue; @@ -1873,7 +1875,16 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b break; } - const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat; + float fSongBeat = GAMESTATE->m_fSongBeat; + + if( GAMESTATE->m_pCurSong ) + { + fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ); + + if( GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber] ) + fSongBeat = m_Timing->GetBeatFromElapsedTime( fPositionSeconds ); + } + const int iSongRow = row == -1 ? BeatToNoteRow( fSongBeat ) : row; if( col != -1 && !bRelease ) @@ -2011,8 +2022,8 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b * "jack hammers." Hmm. */ const int iStepSearchRows = max( - BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, - iSongRow - BeatToNoteRow( GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) ) + BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, + iSongRow - BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) ) ) + ROWS_PER_BEAT; int iRowOfOverlappingNoteOrRow = row; if( row == -1 ) @@ -2039,7 +2050,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b float fNoteOffset = 0.0f; // we need this later if we are autosyncing const float fStepBeat = NoteRowToBeat( iRowOfOverlappingNoteOrRow ); - const float fStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat(fStepBeat); + const float fStepSeconds = m_Timing->GetElapsedTimeFromBeat(fStepBeat); if( row == -1 ) { @@ -2089,7 +2100,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b // Stepped too close to mine? if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) && fSecondsFromExact <= GetWindowSeconds(TW_Mine) && - !GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iSongRow) ) + !m_Timing->IsWarpAtRow(iSongRow) ) score = TNS_HitMine; break; @@ -2564,7 +2575,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) float fThrowAway; int iWarpBeginRow; float fWarpLength; - GAMESTATE->m_pCurSong->m_SongTiming.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength ); + m_Timing->GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength ); iMissIfOlderThanThisRow = BeatToNoteRow( fMissIfOlderThanThisBeat ); if( bFreeze || bDelay ) @@ -2587,7 +2598,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) continue; // Ignore all notes that are skipped via WARPS. - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iter.Row() ) ) + if( m_Timing->IsWarpAtRow( iter.Row() ) ) continue; if( tn.type == TapNote::mine ) @@ -2622,7 +2633,7 @@ void Player::UpdateJudgedRows() int iRow = iter.Row(); // If row is within a warp section, ignore it. -aj - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow(iRow) ) + if( m_Timing->IsWarpAtRow(iRow) ) continue; if( iLastSeenRow != iRow ) @@ -2843,13 +2854,13 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now ) int iCheckpointFrequencyRows = ROWS_PER_BEAT/2; if( CHECKPOINTS_USE_TICKCOUNTS ) { - int tickCurrent = GAMESTATE->m_pCurSong->m_SongTiming.GetTickcountAtRow( iLastRowCrossed ); + int tickCurrent = m_Timing->GetTickcountAtRow( iLastRowCrossed ); // There are some charts that don't want tickcounts involved at all. iCheckpointFrequencyRows = (tickCurrent > 0 ? ROWS_PER_BEAT / tickCurrent : 0); } else if( CHECKPOINTS_USE_TIME_SIGNATURES ) { - TimeSignatureSegment tSignature = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) ); + TimeSignatureSegment tSignature = m_Timing->GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) ); // Most songs are in 4/4 time. The frequency for checking tick counts should reflect that. iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.m_iDenominator / (tSignature.m_iNumerator * 4); @@ -2957,7 +2968,7 @@ void Player::HandleTapRowScore( unsigned row ) #endif // Warp hackery. -aj - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( row ) ) + if( m_Timing->IsWarpAtRow( row ) ) return; if( GAMESTATE->m_bDemonstrationOrJukebox ) @@ -3061,7 +3072,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH #endif // More warp hackery. -aj - if( GAMESTATE->m_pCurSong->m_SongTiming.IsWarpAtRow( iRow ) ) + if( m_Timing->IsWarpAtRow( iRow ) ) return; // don't accumulate combo if AutoPlay is on. diff --git a/src/Player.h b/src/Player.h index b8923b9372..2d699e4913 100644 --- a/src/Player.h +++ b/src/Player.h @@ -10,6 +10,7 @@ #include "ScreenMessage.h" #include "ThemeMetric.h" #include "InputEventPlus.h" +#include "TimingData.h" class ScoreDisplay; class LifeMeter; @@ -147,6 +148,7 @@ protected: PlayerState *m_pPlayerState; /** @brief The player's present stage stats. */ PlayerStageStats *m_pPlayerStageStats; + TimingData *m_Timing; float m_fNoteFieldHeight; bool m_bPaused; From 4afa85c9f940ae52a5683c601acf1533462b7de2 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 02:41:02 -0500 Subject: [PATCH 035/333] [Sprite] Added SetSecondsIntoAnimation(float) Lua binding. --- Docs/Changelog_sm5.txt | 5 +++++ src/Sprite.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 911c512a32..2addb23d65 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,7 +8,12 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/10 +---------- +* [Sprite] Added SetSecondsIntoAnimation(float) Lua binding. [AJ] + 2011/05/03 +---------- * [ScreenEdit] Allow changing the Beat 0 Offset, Music Sample Start, and Music Sample Length via Edit Song Info menu. [Wolfman2000] diff --git a/src/Sprite.cpp b/src/Sprite.cpp index a07beeec01..e34dde8802 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -1130,6 +1130,7 @@ public: static int setstate( T* p, lua_State *L ) { p->SetState( IArg(1) ); return 0; } static int GetState( T* p, lua_State *L ) { lua_pushnumber( L, p->GetState() ); return 1; } static int GetAnimationLengthSeconds( T* p, lua_State *L ) { lua_pushnumber( L, p->GetAnimationLengthSeconds() ); return 1; } + static int SetSecondsIntoAnimation( T* p, lua_State *L ) { p->SetSecondsIntoAnimation(FArg(0)) return 0; } static int SetTexture( T* p, lua_State *L ) { RageTexture *pTexture = Luna::check(L, 1); @@ -1170,6 +1171,7 @@ public: ADD_METHOD( setstate ); ADD_METHOD( GetState ); ADD_METHOD( GetAnimationLengthSeconds ); + ADD_METHOD( SetSecondsIntoAnimation ); ADD_METHOD( SetTexture ); ADD_METHOD( GetTexture ); ADD_METHOD( SetEffectMode ); From b634639e8e99f1c71b317a80eb969ed0ffba240a Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 16:00:47 +0700 Subject: [PATCH 036/333] Write timing tags for SSC files. WARN: This does not work with ScreenEdit, yet! --- src/NotesWriterSSC.cpp | 238 +++++++++++++++++++---------------------- src/Song.cpp | 45 +------- src/TimingData.cpp | 50 +++++++++ src/TimingData.h | 5 + 4 files changed, 168 insertions(+), 170 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3c4ff71a3b..d24f7f5e9f 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -41,6 +41,111 @@ static RString BackgroundChangeToString( const BackgroundChange &bgc ) return s; } +/** + * @brief Turn a vector of lines into a single line joined by newline characters. + * @param lines the list of lines to join. + * @return the joined lines. */ +static RString JoinLineList( vector &lines ) +{ + for( unsigned i = 0; i < lines.size(); ++i ) + TrimRight( lines[i] ); + + // Skip leading blanks. + unsigned j = 0; + while( j < lines.size() && lines.size() == 0 ) + ++j; + + return join( "\r\n", lines.begin()+j, lines.end() ); +} + + +// A utility class to write timing tags more easily! +struct TimingTagWriter { + + vector *m_pvsLines; + RString m_sNext; + + TimingTagWriter( vector *pvsLines ): m_pvsLines (pvsLines) { } + + void Write( const int row, const char *value ) + { + m_pvsLines->push_back( m_sNext + ssprintf( "%.6f=%s", NoteRowToBeat(row), value ) ); + m_sNext = ","; + } + + void Write( const int row, const float value ) { Write( row, ssprintf( "%.6f", value ) ); } + void Write( const int row, const int value ) { Write( row, ssprintf( "%d", value ) ); } + void Write( const int row, const int a, const int b ) { Write( row, ssprintf( "%d=%d", a, b ) ); } + + void Init( const RString sTag ) { m_sNext = "#" + sTag + ":"; } + void Finish( ) { m_pvsLines->push_back( ( m_sNext != "," ? m_sNext : "" ) + ";" ); } + +}; + +static void GetTimingTags( vector &lines, TimingData timing ) +{ + TimingTagWriter w ( &lines ); + + timing.TidyUpData(); + + w.Init( "BPMS" ); + FOREACH_CONST( BPMSegment, timing.m_BPMSegments, bs ) + w.Write( bs->m_iStartRow, bs->GetBPM() ); + w.Finish(); + + w.Init( "STOPS" ); + FOREACH_CONST( StopSegment, timing.m_StopSegments, ss ) + if( !ss->m_bDelay ) + w.Write( ss->m_iStartRow, ss->m_fStopSeconds ); + w.Finish(); + + w.Init( "DELAYS" ); + FOREACH_CONST( StopSegment, timing.m_StopSegments, ss ) + if( ss->m_bDelay ) + w.Write( ss->m_iStartRow, ss->m_fStopSeconds ); + w.Finish(); + + w.Init( "WARPS" ); + FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) + w.Write( ws->m_iStartRow, ws->m_fEndBeat ); + w.Finish(); + + ASSERT( !timing.m_vTimeSignatureSegments.empty() ); + w.Init( "TIMESIGNATURES" ); + FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter ) + w.Write( iter->m_iStartRow, iter->m_iNumerator, iter->m_iDenominator ); + w.Finish(); + + ASSERT( !timing.m_TickcountSegments.empty() ); + w.Init( "TICKCOUNTS" ); + FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, ts ) + w.Write( ts->m_iStartRow, ts->m_iTicks ); + w.Finish(); + + ASSERT( !timing.m_ComboSegments.empty() ); + w.Init( "COMBOS" ); + FOREACH_CONST( ComboSegment, timing.m_ComboSegments, cs ) + w.Write( cs->m_iStartRow, cs->m_iCombo ); + w.Finish(); + + w.Init( "LABELS" ); + FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls ) + w.Write( ls->m_iStartRow, ls->m_sLabel.c_str() ); + w.Finish(); + +} + +static void WriteTimingTags( RageFile &f, const TimingData &timing ) +{ + + vector lines; + + GetTimingTags( lines, timing ); + + f.PutLine( JoinLineList( lines ) ); + +} + /** * @brief Write out the common tags for .SM files. * @param f the file in question. @@ -106,105 +211,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) break; } - f.Write( "#BPMS:" ); - for( unsigned i=0; im_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) ); - vector::const_iterator iter2 = iter; - iter2++; - if( iter2 != out.m_SongTiming.m_vTimeSignatureSegments.end() ) - f.Write( "," ); - } - f.PutLine( ";" ); - - ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() ); - f.Write( "#TICKCOUNTS:" ); - for( unsigned i=0; i &lines ) -{ - for( unsigned i = 0; i < lines.size(); ++i ) - TrimRight( lines[i] ); - - // Skip leading blanks. - unsigned j = 0; - while( j < lines.size() && lines.size() == 0 ) - ++j; - - return join( "\r\n", lines.begin()+j, lines.end() ); -} - /** * @brief Retrieve the individual batches of NoteData. * @param song the Song in question. @@ -307,19 +297,8 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa lines.push_back( ssprintf( "#CREDIT:%s;", SmEscape(in.GetCredit()).c_str() ) ); - /* - * TODO: Remove this block, transplant above code - * below for Split Timing. -Wolfman2000 */ - lines.push_back( "#BPMS:;" ); - lines.push_back( "#STOPS:;" ); - lines.push_back( "#DELAYS:;" ); - lines.push_back( "#WARPS:;" ); - lines.push_back( "#LABELS:;" ); - lines.push_back( "#TIMESIGNATURES:;" ); - lines.push_back( "#TICKCOUNTS:;" ); - lines.push_back( "#ATTACKS:;" ); - lines.push_back( "#COMBOS:;" ); - + GetTimingTags( lines, in.m_Timing ); + RString sNoteData; in.GetSMNoteData( sNoteData ); @@ -350,6 +329,7 @@ bool NotesWriterSSC::Write( RString sPath, const Song &out, const vector } WriteGlobalTags( f, out ); + if( bSavingCache ) { f.PutLine( ssprintf( "// cache tags:" ) ); diff --git a/src/Song.cpp b/src/Song.cpp index a2c5184425..5e0a6d4287 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -488,18 +488,13 @@ void Song::TidyUpData() m_sArtist = "Unknown artist"; TranslateTitles(); - if( m_SongTiming.m_BPMSegments.empty() ) + m_SongTiming.TidyUpData(); + + FOREACH( Steps *, m_vpSteps, s ) { - LOG->UserLog( "Song file", m_sSongDir + m_sSongFileName, "has no BPM segments, default provided." ); - - m_SongTiming.AddBPMSegment( BPMSegment(0, 60) ); + (*s)->m_Timing.TidyUpData(); } - // Make sure the first BPM segment starts at beat 0. - if( m_SongTiming.m_BPMSegments[0].m_iStartRow != 0 ) - m_SongTiming.m_BPMSegments[0].m_iStartRow = 0; - - if( m_fMusicSampleStartSeconds == -1 || m_fMusicSampleStartSeconds == 0 || m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) @@ -790,38 +785,6 @@ void Song::TidyUpData() m_sSongFileName += ".ssc"; } while(0); } - - // If no time signature specified, assume 4/4 time for the whole song. - if( m_SongTiming.m_vTimeSignatureSegments.empty() ) - { - TimeSignatureSegment seg(0, 4, 4); - m_SongTiming.m_vTimeSignatureSegments.push_back( seg ); - } - - /* - * Likewise, if no tickcount signature is specified, assume 2 ticks - * per beat for the entire song. The default of 2 is chosen more - * for compatibility with the Pump Pro series than anything else. - */ - if( m_SongTiming.m_TickcountSegments.empty() ) - { - TickcountSegment seg(0, 2); - m_SongTiming.m_TickcountSegments.push_back( seg ); - } - - // Have a default combo segment of one just in case. - if( m_SongTiming.m_ComboSegments.empty() ) - { - ComboSegment seg(0, 1); - m_SongTiming.m_ComboSegments.push_back( seg ); - } - - // Have a default label segment just in case. - if( m_SongTiming.m_LabelSegments.empty() ) - { - LabelSegment seg(0, "Song Start"); - m_SongTiming.m_LabelSegments.push_back( seg ); - } } void Song::TranslateTitles() diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 022976a349..2f93424bc7 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1090,6 +1090,56 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) this->SetBPMAtRow( iStartRow, fNewBPM ); } +void TimingData::TidyUpData() +{ + // If there are no BPM segments, provide a default. + if( m_BPMSegments.empty() ) + { + LOG->UserLog( "Song file", m_sFile, "has no BPM segments, default provided." ); + + AddBPMSegment( BPMSegment(0, 60) ); + } + + // Make sure the first BPM segment starts at beat 0. + if( m_BPMSegments[0].m_iStartRow != 0 ) + m_BPMSegments[0].m_iStartRow = 0; + + // If no time signature specified, assume 4/4 time for the whole song. + if( m_vTimeSignatureSegments.empty() ) + { + TimeSignatureSegment seg(0, 4, 4); + m_vTimeSignatureSegments.push_back( seg ); + } + + // Likewise, if no tickcount signature is specified, assume 2 ticks + //per beat for the entire song. The default of 2 is chosen more + //for compatibility with the Pump Pro series than anything else. + if( m_TickcountSegments.empty() ) + { + TickcountSegment seg(0, 2); + m_TickcountSegments.push_back( seg ); + } + + // Have a default combo segment of one just in case. + if( m_ComboSegments.empty() ) + { + ComboSegment seg(0, 1); + m_ComboSegments.push_back( seg ); + } + + // Have a default label segment just in case. + if( m_LabelSegments.empty() ) + { + LabelSegment seg(0, "Song Start"); + m_LabelSegments.push_back( seg ); + } + +} + + + + + bool TimingData::HasBpmChanges() const { return m_BPMSegments.size()>1; diff --git a/src/TimingData.h b/src/TimingData.h index 36f1d33456..2c5ad2ecf6 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1321,6 +1321,11 @@ public: void InsertRows( int iStartRow, int iRowsToAdd ); void DeleteRows( int iStartRow, int iRowsToDelete ); + /** + * @brief Tidy up the timing data, e.g. provide default BPMs, labels, tickcounts. + */ + void TidyUpData(); + // Lua void PushSelf( lua_State *L ); /** From d0e9e580302232a84b7083df169c2339c9188ff8 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 16:55:00 +0700 Subject: [PATCH 037/333] [splittiming] make ScreenEdit edit the Steps's timing data only. NOTES: now, newly created songs will have the default timing data (60bpm throughout the song) and NoteFields currently doesn't work yet. --- src/NoteField.cpp | 4 +- src/ScreenEdit.cpp | 133 ++++++++++++++++++++--------------------- src/ScreenEditMenu.cpp | 2 +- 3 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 20e7c08f8b..ea54e2f812 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -742,7 +742,7 @@ void NoteField::DrawPrimitives() // Draw beat bars if( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) { - const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_SongTiming.m_vTimeSignatureSegments; + const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing.m_vTimeSignatureSegments; int iMeasureIndex = 0; FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter ) { @@ -785,7 +785,7 @@ void NoteField::DrawPrimitives() { ASSERT(GAMESTATE->m_pCurSong); - const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; + const TimingData &timing = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing; // BPM text FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg ) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index ce69563960..738c366e32 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -931,7 +931,7 @@ void ScreenEdit::Update( float fDeltaTime ) continue; float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld; - float fStartBeat = max( fStartPlayingAtBeat, m_pSong->m_SongTiming.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); + float fStartBeat = max( fStartPlayingAtBeat, m_pSteps->m_Timing.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); float fEndBeat = max( fStartBeat, GAMESTATE->m_fSongBeat ); fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) ); @@ -976,11 +976,11 @@ void ScreenEdit::Update( float fDeltaTime ) float fLastBeat = NoteRowToBeat(m_iStopPlayingAt); if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING ) { - float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( fLastBeat ); - fLastBeat = m_pSong->m_SongTiming.GetBeatFromElapsedTime( fSeconds + 0.5f ); + float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( fLastBeat ); + fLastBeat = m_pSteps->m_Timing.GetBeatFromElapsedTime( fSeconds + 0.5f ); } - float fStopAtSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; + float fStopAtSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; if( GAMESTATE->m_fMusicSeconds > fStopAtSeconds ) { // loop @@ -1071,7 +1071,7 @@ void ScreenEdit::UpdateTextInfo() RString sText; sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat ); - sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ); + sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ); switch( EDIT_MODE.GetValue() ) { DEFAULT_FAIL( EDIT_MODE.GetValue() ); @@ -1129,7 +1129,7 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Home: break; case EditMode_Full: - sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds ); + sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSteps->m_Timing.m_fBeat0OffsetInSeconds ); sText += ssprintf( PREVIEW_START_FORMAT.GetValue(), PREVIEW_START.GetValue().c_str(), m_pSong->m_fMusicSampleStartSeconds ); sText += ssprintf( PREVIEW_LENGTH_FORMAT.GetValue(), PREVIEW_LENGTH.GetValue().c_str(), m_pSong->m_fMusicSampleLengthSeconds ); break; @@ -1579,7 +1579,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_BPM_UP: case EDIT_BUTTON_BPM_DOWN: { - float fBPM = m_pSong->m_SongTiming.GetBPMAtBeat( GAMESTATE->m_fSongBeat ); + float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_fSongBeat ); float fDelta; switch( EditB ) { @@ -1600,7 +1600,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } float fNewBPM = fBPM + fDelta; - m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM ); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1627,24 +1627,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_SongTiming.m_StopSegments.size(); i++ ) + for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } - if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no StopSegment at the current beat + if( i == m_pSteps->m_Timing.m_StopSegments.size() ) // there is no StopSegment at the current beat { // create a new StopSegment if( fDelta > 0 ) - m_pSong->m_SongTiming.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) ); + m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) ); } else // StopSegment being modified is m_SongTiming.m_StopSegments[i] { - m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i, - m_pSong->m_SongTiming.m_StopSegments.begin()+i+1); + m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; + if( m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) + m_pSteps->m_Timing.m_StopSegments.erase( m_pSteps->m_Timing.m_StopSegments.begin()+i, + m_pSteps->m_Timing.m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1673,13 +1673,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_SongTiming.m_StopSegments.size(); i++ ) + for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSong->m_SongTiming.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } - if( i == m_pSong->m_SongTiming.m_StopSegments.size() ) // there is no delay segment at the current beat + if( i == m_pSteps->m_Timing.m_StopSegments.size() ) // there is no delay segment at the current beat { // create a new delay segment if( fDelta > 0 ) @@ -1687,10 +1687,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } else // delay segment being modified is m_SongTiming.m_StopSegments[i] { - m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSong->m_SongTiming.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSong->m_SongTiming.m_StopSegments.erase( m_pSong->m_SongTiming.m_StopSegments.begin()+i, - m_pSong->m_SongTiming.m_StopSegments.begin()+i+1); + m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; + if( m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) + m_pSteps->m_Timing.m_StopSegments.erase( m_pSteps->m_Timing.m_StopSegments.begin()+i, + m_pSteps->m_Timing.m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1718,7 +1718,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) else fDelta *= 40; } - m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta; + m_pSteps->m_Timing.m_fBeat0OffsetInSeconds += fDelta; (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1900,7 +1900,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( pCourse == NULL ) break; CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; - float fStartTime = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + float fStartTime = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); int iAttack = FindAttackAtTime( ce.attacks, fStartTime ); if( iAttack >= 0 ) @@ -1941,7 +1941,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } else { - fStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); + fStart = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); int iAttack = FindAttackAtTime( ce.attacks, fStart ); if( iAttack >= 0 ) @@ -1950,7 +1950,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( m_NoteFieldEdit.m_iEndMarker == -1 ) fEnd = m_pSong->m_fMusicLengthSeconds; else - fEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); + fEnd = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); } g_fLastInsertAttackPositionSeconds = fStart; g_fLastInsertAttackDurationSeconds = fEnd - fStart; @@ -2265,7 +2265,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB ) fOffsetDelta *= 40; } - m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds += fOffsetDelta; + m_pSteps->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta; } break; } @@ -2381,8 +2381,8 @@ void ScreenEdit::TransitionEditState( EditState em ) AdjustSync::ResetOriginalSyncData(); /* Give a 1 second lead-in. If we're loading Player, this must be done first. */ - float fSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; - GAMESTATE->UpdateSongPosition( fSeconds, m_pSong->m_SongTiming ); + float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; + GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing ); GAMESTATE->m_bGameplayLeadIn.Set( false ); @@ -2463,7 +2463,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_PLAYING: case STATE_RECORDING: - const float fStartSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); + const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); LOG->Trace( "Starting playback at %f", fStartSeconds ); RageSoundParams p; @@ -2627,21 +2627,21 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fBPM > 0 ) - m_pSong->m_SongTiming.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2649,7 +2649,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = atoi( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - m_pSong->m_SongTiming.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); + m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); } SetDirty( true ); } @@ -2658,7 +2658,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = atoi( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - m_pSong->m_SongTiming.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); + m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); } SetDirty( true ); } @@ -2667,7 +2667,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - m_pSong->m_SongTiming.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); + m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); } SetDirty( true ); } @@ -2676,25 +2676,25 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - m_pSong->m_SongTiming.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); + m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); } SetDirty( true ); } else if ( SM == SM_BackFromLabelChange ) { RString sLabel = ScreenTextEntry::s_sLastAnswer; - if ( !m_pSong->m_SongTiming.DoesLabelExist(sLabel) ) + if ( !m_pSteps->m_Timing.DoesLabelExist(sLabel) ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - m_pSong->m_SongTiming.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); + m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - m_pSong->m_SongTiming.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); + m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -2767,7 +2767,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; int iAttack; - g_fLastInsertAttackPositionSeconds = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + g_fLastInsertAttackPositionSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] ); iAttack = FindAttackAtTime( ce.attacks, g_fLastInsertAttackPositionSeconds ); @@ -3024,7 +3024,7 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); + GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } static void ChangeLastBeatHint( const RString &sNew ) @@ -3255,9 +3255,8 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case edit_timing_data: { - const Song* pSong = GAMESTATE->m_pCurSong; - TimingData pTime = pSong->m_SongTiming; - const float fBeat = GAMESTATE->m_fSongBeat; + TimingData pTime = m_pSteps->m_Timing; + const float fBeat = pTime.GetBeatFromElapsedTime(GAMESTATE->m_fMusicSeconds); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); @@ -3501,7 +3500,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex ); // scale timing data - m_pSong->m_SongTiming.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); + m_pSteps->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); // scale all other steps. const vector sIter = m_pSong->GetAllSteps(); @@ -3546,16 +3545,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_forward: - m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_backward: - m_pSong->m_SongTiming.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); break; case convert_to_pause: { ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ); - float fMarkerStart = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); - float fMarkerEnd = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); + float fMarkerStart = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); + float fMarkerEnd = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); // The length of the stop segment we're going to create. This includes time spent in any // stops in the selection, which will be deleted and subsumed into the new stop. @@ -3567,9 +3566,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns m_NoteFieldEdit.m_iBeginMarker + 1, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSong->m_SongTiming.DeleteRows( m_NoteFieldEdit.m_iBeginMarker, + m_pSteps->m_Timing.DeleteRows( m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSong->m_SongTiming.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); + m_pSteps->m_Timing.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); m_NoteFieldEdit.m_iBeginMarker = -1; m_NoteFieldEdit.m_iEndMarker = -1; break; @@ -3577,14 +3576,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_pause_to_beat: { // TODO: Convert both Delays and Stops at once. - float fStopSeconds = m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ); - m_pSong->m_SongTiming.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 ); + float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 ); - float fStopBeats = fStopSeconds * m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60; + float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60; // don't move the step from where it is, just move everything later NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSong->m_SongTiming.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: @@ -3701,7 +3700,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec break; case beat_0_offset: ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, - ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds), 20, + ssprintf("%.5f", m_pSteps->m_Timing.m_fBeat0OffsetInSeconds), 20, ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); break; case last_beat_hint: @@ -3750,7 +3749,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, - ssprintf( "%.4f", m_pSong->m_SongTiming.GetBPMAtBeat(GAMESTATE->m_fSongBeat) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_fSongBeat) ), 10 ); break; @@ -3758,7 +3757,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromStopChange, ENTER_STOP_VALUE, - ssprintf( "%.4f", m_pSong->m_SongTiming.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; @@ -3766,7 +3765,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromDelayChange, ENTER_DELAY_VALUE, - ssprintf( "%.4f", m_pSong->m_SongTiming.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; @@ -3774,7 +3773,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureNumeratorChange, ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ), 3 ); break; @@ -3782,7 +3781,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureDenominatorChange, ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", m_pSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ), 3 ); break; @@ -3790,7 +3789,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTickcountChange, ENTER_TICKCOUNT_VALUE, - ssprintf( "%d", m_pSong->m_SongTiming.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ), 2 ); break; @@ -3798,7 +3797,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromComboChange, ENTER_COMBO_VALUE, - ssprintf( "%d", m_pSong->m_SongTiming.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), 4 ); break; @@ -3806,7 +3805,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromLabelChange, ENTER_LABEL_VALUE, - ssprintf( "%s", m_pSong->m_SongTiming.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), + ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), 64 ); break; @@ -3814,7 +3813,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", m_pSong->m_SongTiming.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), 10 ); break; diff --git a/src/ScreenEditMenu.cpp b/src/ScreenEditMenu.cpp index 04bb81e213..1bf4997aea 100644 --- a/src/ScreenEditMenu.cpp +++ b/src/ScreenEditMenu.cpp @@ -236,7 +236,7 @@ void ScreenEditMenu::MenuStart( const InputEventPlus &input ) case EditMenuAction_Create: ASSERT( !pSteps ); { - pSteps = new Steps; + pSteps = pSong->CreateSteps(); switch( m_Selector.EDIT_MODE ) { From ce91d1a4314e5ab78a00089bf4db0593b04cfe47 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 17:44:12 +0700 Subject: [PATCH 038/333] [splittiming] load split timing from ssc files --- src/NotesLoaderSM.cpp | 7 ++++- src/NotesLoaderSM.h | 2 +- src/NotesLoaderSSC.cpp | 59 ++++++++++++++++++++---------------------- src/NotesLoaderSSC.h | 2 -- src/Song.cpp | 6 +++++ 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 3fa6432713..a8633ba3d8 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -103,7 +103,7 @@ bool SMLoader::LoadTimingFromFile( const RString &fn, TimingData &out ) return true; } -void SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) +bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) { vector arrayBPMChangeExpressions; split( sParam, ",", arrayBPMChangeExpressions ); @@ -112,6 +112,7 @@ void SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) float negBeat = -1; float negBPM = 1; float highspeedBeat = -1; + bool bNotEmpty = false; for( unsigned b=0; bm_Timing = out.m_Timing; + if( bHasOwnTiming ) + pNewNotes->m_Timing = stepsTiming; pNewNotes->SetSMNoteData( sParams[1] ); pNewNotes->TidyUpData(); out.AddSteps( pNewNotes ); } - - else if( sValueName=="BPMS" ) // This must ALWAYS be here in Split Timing. + + else if( sValueName=="BPMS" ) { - state = GETTING_STEP_TIMING_INFO; - /* - pNewNotes->m_Timing = TimingData(out.m_SongTiming.m_fBeat0OffsetInSeconds); - SMLoader::ProcessBPMs(pNewNotes->m_Timing, sParams[1]); - */ - + if( SMLoader::ProcessBPMs(stepsTiming, sParams[1]) ) + bHasOwnTiming = true; } - break; - } - case GETTING_STEP_TIMING_INFO: - { - if( sValueName=="STOPS" ) + + else if( sValueName=="STOPS" ) { - // SMLoader::ProcessStops(pNewNotes->m_Timing, sParams[1]); + SMLoader::ProcessStops(stepsTiming, sParams[1]); } + else if( sValueName=="DELAYS" ) { - // SMLoader::ProcessDelays(pNewNotes->m_Timing, sParams[1]); + SMLoader::ProcessDelays(stepsTiming, sParams[1]); } + else if( sValueName=="TIMESIGNATURES" ) { - // SMLoader::ProcessTimeSignatures(pNewNotes->m_Timing, sParams[1]); + SMLoader::ProcessTimeSignatures(stepsTiming, sParams[1]); } + else if( sValueName=="TICKCOUNTS" ) { - // SMLoader::ProcessTickcounts(pNewNotes->m_Timing, sParams[1]); + SMLoader::ProcessTickcounts(stepsTiming, sParams[1]); } + else if( sValueName=="COMBOS" ) { - // ProcessCombos(pNewNotes->m_Timing, sParams[1]); + ProcessCombos(stepsTiming, sParams[1]); } + else if( sValueName=="WARPS" ) { - // ProcessWarps(pNewNotes->m_Timing, sParams[1]); + ProcessWarps(stepsTiming, sParams[1]); } + else if( sValueName=="LABELS" ) { - // ProcessLabels(pNewNotes->m_Timing, sParams[1]); + ProcessLabels(stepsTiming, sParams[1]); } + else if( sValueName=="ATTACKS" ) { // TODO: Look into Step attacks vs Song Attacks. -Wolfman2000 @@ -635,18 +640,10 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach } */ } + else if( sValueName=="OFFSET" ) - {/* - pNewNotes->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); - */ - } - - else if( sValueName=="NOTES" || sValueName=="NOTES2" ) { - state = GETTING_SONG_INFO; - pNewNotes->SetSMNoteData( sParams[1] ); - pNewNotes->TidyUpData(); - out.AddSteps( pNewNotes ); + stepsTiming.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); } break; } diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index bf85bdd73c..7d185cc690 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -16,8 +16,6 @@ enum SSCLoadingStates { GETTING_SONG_INFO, /**< Retrieving song information. */ GETTING_STEP_INFO, /**< Retrieving step information. */ - GETTING_STEP_TIMING_INFO, /**< Retrieving a step's individual timing information. */ - GETTING_NOTE_INFO, /**< Retrieving the specific notes. This state may be deprecated. */ NUM_SSCLoadingStates /**< The number of states used. */ }; diff --git a/src/Song.cpp b/src/Song.cpp index 5e0a6d4287..c5986b0284 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -863,6 +863,12 @@ void Song::Save() ReCalculateRadarValuesAndLastBeat(); TranslateTitles(); + + // TODO: Figure out a better way to save to Song's timing data. + if( m_vpSteps.size() == 1 ) + { + m_SongTiming = m_vpSteps[0]->m_Timing; + } // Save the new files. These calls make backups on their own. if( !SaveToSSCFile(GetSongFilePath(), false) ) From 241738c18b97618bae76a82323d5d94fa483ea28 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 19:54:05 +0700 Subject: [PATCH 039/333] [splittiming] Let's break things again! (222) We introduced a new class, called "SongPosition", that replaces some instance variables in the GameState class. (GameState::m_Position). Then, you also have it in PlayerState class which keeps track of the position based on their steps. (PlayerState::m_Position). Fixing the build errors: - GAMESTATE->m_fSomething should now be: - GAMESTATE->m_Position.m_fSomething - pPlayerState->m_Position.m_fSomething (or m_pPlayerState for some instance!) --- Xcode/stepmania.xcodeproj/project.pbxproj | 8 +++ src/GameState.cpp | 52 ++--------------- src/GameState.h | 25 +------- src/Player.cpp | 6 +- src/PlayerState.h | 4 ++ src/SongPosition.cpp | 63 +++++++++++++++++++++ src/SongPosition.h | 69 +++++++++++++++++++++++ 7 files changed, 156 insertions(+), 71 deletions(-) create mode 100644 src/SongPosition.cpp create mode 100644 src/SongPosition.h diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index a70652bcd4..30eba612d7 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -1653,6 +1653,8 @@ AAFF41A40F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = AAFF41A20F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h */; }; AAFF41A50F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAFF41A10F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.cpp */; }; AAFF41A60F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = AAFF41A20F5BD4AD00FFDB67 /* ScreenOptionsExportPackage.h */; }; + B75CE3B5137963350076A82D /* SongPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = B75CE3B3137963350076A82D /* SongPosition.h */; }; + B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B75CE3B4137963350076A82D /* SongPosition.cpp */; }; EE2153A910A75BEE0074B01B /* NotesLoaderPMS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */; }; EE2153AA10A75BEE0074B01B /* NotesLoaderPMS.h in Headers */ = {isa = PBXBuildFile; fileRef = EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */; }; EE879B60132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE879B5C132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp */; }; @@ -3017,6 +3019,8 @@ AAFF55220549F43A00D02EE9 /* ComboGraph.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ComboGraph.h; path = ../src/ComboGraph.h; sourceTree = ""; }; AAFF5541054E736D00D02EE9 /* Attack.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; name = Attack.cpp; path = ../src/Attack.cpp; sourceTree = ""; }; AAFF5542054E736D00D02EE9 /* Attack.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = Attack.h; path = ../src/Attack.h; sourceTree = ""; }; + B75CE3B3137963350076A82D /* SongPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SongPosition.h; path = ../src/SongPosition.h; sourceTree = SOURCE_ROOT; }; + B75CE3B4137963350076A82D /* SongPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SongPosition.cpp; path = ../src/SongPosition.cpp; sourceTree = SOURCE_ROOT; }; EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderPMS.cpp; path = ../src/NotesLoaderPMS.cpp; sourceTree = SOURCE_ROOT; }; EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderPMS.h; path = ../src/NotesLoaderPMS.h; sourceTree = SOURCE_ROOT; }; EE879B5C132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RageDisplay_Legacy_Helpers.cpp; path = ../src/RageDisplay_Legacy_Helpers.cpp; sourceTree = SOURCE_ROOT; }; @@ -3925,6 +3929,8 @@ AA7CDD930D8395F90001DAFC /* Song.h */, AA6EFE0704770C79005F316C /* SongOptions.cpp */, AA6EFE0804770C79005F316C /* SongOptions.h */, + B75CE3B4137963350076A82D /* SongPosition.cpp */, + B75CE3B3137963350076A82D /* SongPosition.h */, AA5C73F90637A5F000AFB891 /* SongUtil.cpp */, AA5C73FA0637A5F000AFB891 /* SongUtil.h */, AAEBF57C0B5C83F4005F3C7C /* SoundEffectControl.cpp */, @@ -5042,6 +5048,7 @@ 2BC6132D13773C8E00CC8BBD /* pngpriv.h in Headers */, 2BC6133313773C8E00CC8BBD /* pngstruct.h in Headers */, 2BC6133E13773D2C00CC8BBD /* pnglibconf.h in Headers */, + B75CE3B5137963350076A82D /* SongPosition.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6301,6 +6308,7 @@ 2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */, 2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */, 2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */, + B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/GameState.cpp b/src/GameState.cpp index 90792cad8c..6f3dc9f6a0 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -951,53 +951,13 @@ static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) { - if( !timestamp.IsZero() ) - m_LastBeatUpdate = timestamp; - else - m_LastBeatUpdate.Touch(); + + m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); - // xxx testing: only do this on monotune survivor - /* - if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) - LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); - */ - - timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); - // "Crash reason : -243478.890625 -48695.773438" - ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); - - m_fMusicSeconds = fPositionSeconds; - - m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds ); - - m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); - - m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); - float fThrowAway, fThrowAway2; - bool bThrowAway; - int iThrowAway; - timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); - - /* - // xxx testing: only do this on monotune survivor - if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) - { - // and only do it in the known negative bpm region. HACKITY HACK - if(m_fSongBeat >= 445.490f && m_fSongBeat <= 453.72f) - { - LOG->Trace( ssprintf("fPositionSeconds = %f",fPositionSeconds) ); - LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); - //LOG->Trace( ssprintf("Music seconds visible %f = fPositionSeconds %f - g_fVisualDelaySeconds %f", m_fMusicSecondsVisible,fPositionSeconds,g_fVisualDelaySeconds.Get()) ); - } - else if(m_fSongBeat == 445.500f) - { - LOG->Trace( ssprintf("[beat 445.500] fPositionSeconds = %f",fPositionSeconds) ); - LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); - } - } - */ - - Actor::SetBGMTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fPositionSeconds, m_fSongBeatNoOffset ); + FOREACH_EnabledPlayer( pn ) + m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); + + Actor::SetBGMTime( m_Position.m_fMusicSecondsVisible, m_Position.m_fSongBeatVisible, m_Position.fPositionSeconds, m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } diff --git a/src/GameState.h b/src/GameState.h index 406e4784b1..9b192156c3 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -10,6 +10,7 @@ #include "RageTimer.h" #include "PlayerOptions.h" #include "SongOptions.h" +#include "SongPosition.h" #include "Preference.h" #include @@ -194,29 +195,9 @@ public: bool m_bBackedOutOfFinalStage; // Music statistics: - // Arcade - the current stage (one song). - // Oni/Endless - a single song in a course. - // Let a lot of classes access this info here so they don't have to keep their own copies. - // todo: [NUM_PLAYERS] this for split bpm lolol -aj - float m_fMusicSeconds; // time into the current song, not scaled by music rate - float m_fSongBeat; - float m_fSongBeatNoOffset; - float m_fCurBPS; - float m_fLightSongBeat; // g_fLightsFalloffSeconds ahead - //bool m_bStop; // in the middle of a stop (freeze or delay) - /** @brief A flag to determine if we're in the middle of a freeze/stop. */ - bool m_bFreeze; - /** @brief A flag to determine if we're in the middle of a delay (Pump style stop). */ - bool m_bDelay; - /** @brief The row used to start a warp. */ - int m_iWarpBeginRow; - /** @brief The beat to warp to afterwards. */ - float m_fWarpDestination; - RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update - BroadcastOnChange m_bGameplayLeadIn; + SongPosition m_Position; - float m_fMusicSecondsVisible; - float m_fSongBeatVisible; + BroadcastOnChange m_bGameplayLeadIn; // if re-adding noteskin changes in courses, add functions and such here -aj void GetAllUsedNoteSkins( vector &out ) const; diff --git a/src/Player.cpp b/src/Player.cpp index 95353c1669..1843553ade 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -506,7 +506,7 @@ void Player::Load() m_LastTapNoteScore = TNS_None; // The editor can start playing in the middle of the song. - const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ); + const int iNoteRow = BeatToNoteRowNotRounded( m_pPlayerState->m_Position.m_fSongBeat ); m_iFirstUncrossedRow = iNoteRow - 1; m_pJudgedRows->Reset( iNoteRow ); @@ -695,7 +695,7 @@ void Player::Update( float fDeltaTime ) return; } - const float fSongBeat = GAMESTATE->m_fSongBeat; + const float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); // Optimization: Don't spend time processing the things below that won't show @@ -797,7 +797,7 @@ void Player::Update( float fDeltaTime ) // Check for a strum miss if( m_pPlayerState->m_fLastStrumMusicSeconds != -1 && - m_pPlayerState->m_fLastStrumMusicSeconds + g_fTimingWindowStrum < GAMESTATE->m_fMusicSeconds ) + m_pPlayerState->m_fLastStrumMusicSeconds + g_fTimingWindowStrum < m_pPlayerState->m_Position.m_fMusicSeconds ) { DoStrumMiss(); } diff --git a/src/PlayerState.h b/src/PlayerState.h index 6df9dc662d..59239ca915 100644 --- a/src/PlayerState.h +++ b/src/PlayerState.h @@ -3,6 +3,7 @@ #ifndef PlayerState_H #define PlayerState_H +#include "SongPosition.h" #include "Attack.h" #include "ModsGroup.h" #include "PlayerNumber.h" @@ -38,6 +39,9 @@ public: */ MultiPlayer m_mp; + // Music statistics: + SongPosition m_Position; + /** * @brief Change the PlayerOptions to their default. * @param l the level of mods to reset. diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp new file mode 100644 index 0000000000..c3e6c30ffc --- /dev/null +++ b/src/SongPosition.cpp @@ -0,0 +1,63 @@ +/* + * SongPosition.cpp + * stepmania + * + * Created by [Full Username] on 5/10/11. + * Copyright 2011 [Organization Name]. All rights reserved. + * + */ + +#include "SongPosition.h" + +void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) +{ + + if( !timestamp.IsZero() ) + m_LastBeatUpdate = timestamp; + else + m_LastBeatUpdate.Touch(); + + // xxx testing: only do this on monotune survivor + /* + if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) + LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); + */ + + timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); + + // "Crash reason : -243478.890625 -48695.773438" + ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); + + m_fMusicSeconds = fPositionSeconds; + + m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds ); + + m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); + + m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); + float fThrowAway, fThrowAway2; + bool bThrowAway; + int iThrowAway; + timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); + + /* + // xxx testing: only do this on monotune survivor + if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) + { + // and only do it in the known negative bpm region. HACKITY HACK + if(m_fSongBeat >= 445.490f && m_fSongBeat <= 453.72f) + { + LOG->Trace( ssprintf("fPositionSeconds = %f",fPositionSeconds) ); + LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); + //LOG->Trace( ssprintf("Music seconds visible %f = fPositionSeconds %f - g_fVisualDelaySeconds %f", m_fMusicSecondsVisible,fPositionSeconds,g_fVisualDelaySeconds.Get()) ); + } + else if(m_fSongBeat == 445.500f) + { + LOG->Trace( ssprintf("[beat 445.500] fPositionSeconds = %f",fPositionSeconds) ); + LOG->Trace( ssprintf("Song beat: %f (%f seconds), BPS = %f (%f BPM)",m_fSongBeat,m_fMusicSecondsVisible,m_fCurBPS,m_fCurBPS*60.0f) ); + } + } + */ + + +} diff --git a/src/SongPosition.h b/src/SongPosition.h new file mode 100644 index 0000000000..8890e3a87d --- /dev/null +++ b/src/SongPosition.h @@ -0,0 +1,69 @@ +#ifndef SONGPOSITION_H +#define SONGPOSITION_H + +#include "GameConstantsAndTypes.h" +#include "RageTimer.h" +#include "LightsManager.h" +#include "MessageManager.h" +#include "TimingData.h" + +class SongPosition +{ + + public: + + // Arcade - the current stage (one song). + // Oni/Endless - a single song in a course. + // Let a lot of classes access this info here so they don't have to keep their own copies. + // todo: [NUM_PLAYERS] this for split bpm lolol -aj + float m_fMusicSeconds; // time into the current song, not scaled by music rate + float m_fSongBeat; + float m_fSongBeatNoOffset; + float m_fCurBPS; + float m_fLightSongBeat; // g_fLightsFalloffSeconds ahead + //bool m_bStop; // in the middle of a stop (freeze or delay) + /** @brief A flag to determine if we're in the middle of a freeze/stop. */ + bool m_bFreeze; + /** @brief A flag to determine if we're in the middle of a delay (Pump style stop). */ + bool m_bDelay; + /** @brief The row used to start a warp. */ + int m_iWarpBeginRow; + /** @brief The beat to warp to afterwards. */ + float m_fWarpDestination; + RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update + + float m_fMusicSecondsVisible; + float m_fSongBeatVisible; + + void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); + +}; + +#endif + +/** + * @file + * @author Chris Danford, Glenn Maynard (c) 2001-2004 + * @section LICENSE + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ From 5d4c63bf5ace421a700f5db02e6d1fbde555481c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 08:58:24 -0400 Subject: [PATCH 040/333] [splittiming] The .edit files matter too. Maybe we need a new extension for edits. --- src/NotesLoaderSSC.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index ab7da6b480..59c7aed3ee 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -684,6 +684,8 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat Song* pSong = NULL; Steps* pNewNotes = NULL; bool bSSCFormat = false; + bool bHasOwnTiming = false; + TimingData stepsTiming; for( unsigned i=0; im_Timing = stepsTiming; + } pNewNotes->SetSMNoteData( sParams[1] ); pNewNotes->TidyUpData(); pSong->AddSteps( pNewNotes ); From d8068767bb0bf676a427808b303c343fe1f6c8b4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 09:02:31 -0400 Subject: [PATCH 041/333] [splittiming] Thai, your file. Your credit. --- src/SongPosition.cpp | 37 ++++++++++++++++++++++++++++--------- src/SongPosition.h | 2 +- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index c3e6c30ffc..60c5587016 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -1,12 +1,3 @@ -/* - * SongPosition.cpp - * stepmania - * - * Created by [Full Username] on 5/10/11. - * Copyright 2011 [Organization Name]. All rights reserved. - * - */ - #include "SongPosition.h" void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) @@ -61,3 +52,31 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData } + +/** + * @file + * @author Thai Pangsakulyanont (c) 2011 + * @section LICENSE + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + diff --git a/src/SongPosition.h b/src/SongPosition.h index 8890e3a87d..1e4226ef84 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -43,7 +43,7 @@ class SongPosition /** * @file - * @author Chris Danford, Glenn Maynard (c) 2001-2004 + * @author Thai Pangsakulyanont (c) 2011 * @section LICENSE * All rights reserved. * From e1e605b736b369850fccf6b4dcb1239db4202038 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 20:03:51 +0700 Subject: [PATCH 042/333] [splittiming] move bogus variables back to GameState (210) --- src/GameState.cpp | 8 +++++++- src/GameState.h | 2 ++ src/SongPosition.cpp | 7 ------- src/SongPosition.h | 3 --- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 6f3dc9f6a0..9ad930dcd3 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -957,7 +957,13 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti FOREACH_EnabledPlayer( pn ) m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); - Actor::SetBGMTime( m_Position.m_fMusicSecondsVisible, m_Position.m_fSongBeatVisible, m_Position.fPositionSeconds, m_Position.m_fSongBeatNoOffset ); + m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); + float fThrowAway, fThrowAway2; + bool bThrowAway; + int iThrowAway; + timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); + + Actor::SetBGMTime( m_Position.m_fMusicSecondsVisible, m_Position.m_fSongBeatVisible, fPositionSeconds, m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } diff --git a/src/GameState.h b/src/GameState.h index 9b192156c3..f0446c28b8 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -196,6 +196,8 @@ public: // Music statistics: SongPosition m_Position; + float m_fMusicSecondsVisible; + float m_fSongBeatVisible; BroadcastOnChange m_bGameplayLeadIn; diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index c3e6c30ffc..f6e6afb35b 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -34,12 +34,6 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); - m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); - float fThrowAway, fThrowAway2; - bool bThrowAway; - int iThrowAway; - timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); - /* // xxx testing: only do this on monotune survivor if( m_pCurSong && m_pCurSong->GetDisplayFullTitle() == "monotune survivor" ) @@ -59,5 +53,4 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData } */ - } diff --git a/src/SongPosition.h b/src/SongPosition.h index 8890e3a87d..4571ca29d4 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -32,9 +32,6 @@ class SongPosition float m_fWarpDestination; RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update - float m_fMusicSecondsVisible; - float m_fSongBeatVisible; - void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); }; From 38a4852180b28eef3257bc70fbf9a68b4bece22f Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 20:18:17 +0700 Subject: [PATCH 043/333] [splittiming] Fix Player.cpp (198) --- src/Player.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index 1843553ade..e885c2bf9c 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -919,12 +919,12 @@ void Player::Update( float fDeltaTime ) /* We want to send the crossed row message exactly when we cross the row--not * .5 before the row. Use a very slow song (around 2 BPM) as a test case: without * rounding, autoplay steps early. -glenn */ - const int iRowNow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ); + const int iRowNow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat ); if( iRowNow >= 0 ) { if( GAMESTATE->IsPlayerEnabled(m_pPlayerState) ) { - if(GAMESTATE->m_bDelay) + if(m_pPlayerState->m_Position.m_bDelay) { if( !m_bDelay ) m_bDelay = true; @@ -1652,7 +1652,7 @@ void Player::Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRele } // Handle hammer-ons and pull-offs - const float fPositionSeconds = GAMESTATE->m_fMusicSeconds - tm.Ago(); + const float fPositionSeconds = m_pPlayerState->m_Position.m_fMusicSeconds - tm.Ago(); int iHopoCol = -1; bool bDoHopo = m_pPlayerState->m_fLastHopoNoteMusicSeconds != -1 && @@ -1705,7 +1705,7 @@ void Player::Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRele // Check if this fret breaks all active holds. if( !bRelease ) { - const float fSongBeat = GAMESTATE->m_fSongBeat; + const float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); int iMaxHoldCol = -1; @@ -1747,7 +1747,7 @@ void Player::Strum( int col, int row, const RageTimer &tm, bool bHeld, bool bRel DoStrumMiss(); } - m_pPlayerState->m_fLastStrumMusicSeconds = GAMESTATE->m_fMusicSeconds; + m_pPlayerState->m_fLastStrumMusicSeconds = m_pPlayerState->m_Position.m_fMusicSeconds; StepStrumHopo( col, row, tm, bHeld, bRelease, ButtonType_StrumFretsChanged ); } @@ -1796,7 +1796,7 @@ void Player::ScoreAllActiveHoldsLetGo() { if( PENALIZE_TAP_SCORE_NONE ) { - const float fSongBeat = GAMESTATE->m_fSongBeat; + const float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); // Score all active holds to NotHeld @@ -1859,8 +1859,8 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b // Do everything that depends on a RageTimer here; // set your breakpoints somewhere after this block. - const float fLastBeatUpdate = GAMESTATE->m_LastBeatUpdate.Ago(); - const float fPositionSeconds = GAMESTATE->m_fMusicSeconds - tm.Ago(); + const float fLastBeatUpdate = m_pPlayerState->m_Position.m_LastBeatUpdate.Ago(); + const float fPositionSeconds = m_pPlayerState->m_Position.m_fMusicSeconds - tm.Ago(); const float fTimeSinceStep = tm.Ago(); switch( pbt ) @@ -1875,7 +1875,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b break; } - float fSongBeat = GAMESTATE->m_fSongBeat; + float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; if( GAMESTATE->m_pCurSong ) { @@ -2059,7 +2059,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b /* GAMESTATE->m_fMusicSeconds is the music time as of GAMESTATE->m_LastBeatUpdate. Figure * out what the music time is as of now. */ - const float fCurrentMusicSeconds = GAMESTATE->m_fMusicSeconds + (fLastBeatUpdate*GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate); + const float fCurrentMusicSeconds = m_pPlayerState->m_Position.m_fMusicSeconds + (fLastBeatUpdate*GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate); // ... which means it happened at this point in the music: const float fMusicSeconds = fCurrentMusicSeconds - fTimeSinceStep * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; @@ -2568,7 +2568,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) { //LOG->Trace( "Steps::UpdateTapNotesMissedOlderThan(%f)", fMissIfOlderThanThisBeat ); int iMissIfOlderThanThisRow; - const float fEarliestTime = GAMESTATE->m_fMusicSeconds - fMissIfOlderThanSeconds; + const float fEarliestTime = m_pPlayerState->m_Position.m_fMusicSeconds - fMissIfOlderThanSeconds; { bool bFreeze, bDelay; float fMissIfOlderThanThisBeat; @@ -2621,7 +2621,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) void Player::UpdateJudgedRows() { - const int iEndRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + const int iEndRow = BeatToNoteRow( m_pPlayerState->m_Position.m_fSongBeat ); bool bAllJudged = true; const bool bSeparately = GAMESTATE->GetCurrentGame()->m_bCountNotesSeparately; @@ -3268,7 +3268,7 @@ void Player::SetCombo( int iCombo, int iMisses ) } else { - bPastBeginning = GAMESTATE->m_fMusicSeconds > GAMESTATE->m_pCurSong->m_fMusicLengthSeconds * PERCENT_UNTIL_COLOR_COMBO; + bPastBeginning = m_pPlayerState->m_Position.m_fMusicSeconds > GAMESTATE->m_pCurSong->m_fMusicLengthSeconds * PERCENT_UNTIL_COLOR_COMBO; } if( m_bSendJudgmentAndComboMessages ) From ab8b76b3b85ad35405f161d7626eda86a34f76c0 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 20:27:12 +0700 Subject: [PATCH 044/333] [splittiming] NoteDisplay, NoteField, Player, PlayerState (182) --- src/NoteDisplay.cpp | 2 +- src/NoteField.cpp | 14 +++++++------- src/Player.cpp | 4 ++-- src/PlayerState.cpp | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/NoteDisplay.cpp b/src/NoteDisplay.cpp index 3998c1fb08..a5c530bd73 100644 --- a/src/NoteDisplay.cpp +++ b/src/NoteDisplay.cpp @@ -286,7 +286,7 @@ void NoteDisplay::Update( float fDeltaTime ) void NoteDisplay::SetActiveFrame( float fNoteBeat, Actor &actorToSet, float fAnimationLength, bool bVivid ) { /* -inf ... inf */ - float fBeatOrSecond = cache->m_bAnimationBasedOnBeats ? GAMESTATE->m_fSongBeat : GAMESTATE->m_fMusicSeconds; + float fBeatOrSecond = cache->m_bAnimationBasedOnBeats ? m_pPlayerState->m_Position.m_fSongBeat : m_pPlayerState->m_Position.m_fMusicSeconds; /* -len ... +len */ float fPercentIntoAnimation = fmodf( fBeatOrSecond, fAnimationLength ); /* -1 ... 1 */ diff --git a/src/NoteField.cpp b/src/NoteField.cpp index ea54e2f812..c4c6826765 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -240,7 +240,7 @@ void NoteField::Update( float fDeltaTime ) ActorFrame::Update( fDeltaTime ); // update m_fBoardOffsetPixels, m_fCurrentBeatLastUpdate, m_fYPosCurrentBeatLastUpdate - const float fCurrentBeat = GAMESTATE->m_fSongBeat; + const float fCurrentBeat = m_pPlayerState->m_Position.m_fSongBeat; bool bTweeningOn = m_sprBoard->GetCurrentDiffuseAlpha() >= 0.98 && m_sprBoard->GetCurrentDiffuseAlpha() < 1.00; // HACK if( !bTweeningOn && m_fCurrentBeatLastUpdate != -1 ) { @@ -606,7 +606,7 @@ void NoteField::DrawBGChangeText( const float fBeat, const RString sNewBGName ) // change this probing to binary search float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceAfterTargetsPixels ) { - float fFirstBeatToDraw = GAMESTATE->m_fSongBeat-4; // Adjust to balance off performance and showing enough notes. + float fFirstBeatToDraw = pPlayerState->m_Position.m_fSongBeat-4; // Adjust to balance off performance and showing enough notes. /* In Boomerang, we'll usually have two sections of notes: before and after * the peak. We always start drawing before the peak, and end after it, or @@ -618,7 +618,7 @@ float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistance bBoomerang = (fAccels[PlayerOptions::ACCEL_BOOMERANG] != 0); } - while( fFirstBeatToDraw < GAMESTATE->m_fSongBeat ) + while( fFirstBeatToDraw < m_pPlayerState->m_Position.m_fSongBeat ) { bool bIsPastPeakYOffset; float fPeakYOffset; @@ -640,7 +640,7 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB // Probe for last note to draw. Worst case is 0.25x + boost. // Adjust search distance so that notes don't pop onto the screen. float fSearchDistance = 10; - float fLastBeatToDraw = GAMESTATE->m_fSongBeat+fSearchDistance; + float fLastBeatToDraw = pPlayerState->m_Position.m_fSongBeat+fSearchDistance; const int NUM_ITERATIONS = 20; @@ -1045,7 +1045,7 @@ void NoteField::DrawPrimitives() displayCols->display[c].DrawHold( tn, c, iStartRow, bIsHoldingNote, Result, bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, m_fYReverseOffsetPixels, (float) iDrawDistanceAfterTargetsPixels, (float) iDrawDistanceBeforeTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT ); - bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > GAMESTATE->m_fSongBeat; + bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > m_pPlayerState->m_Position.m_fSongBeat; bAnyUpcomingInThisCol |= bNoteIsUpcoming; } } @@ -1087,7 +1087,7 @@ void NoteField::DrawPrimitives() continue; // skip ASSERT_M( NoteRowToBeat(q) > -2000, ssprintf("%i %i %i, %f %f", q, iLastRowToDraw, - iFirstRowToDraw, GAMESTATE->m_fSongBeat, GAMESTATE->m_fMusicSeconds) ); + iFirstRowToDraw, m_pPlayerState->m_Position.m_fSongBeat, m_pPlayerState->m_Position.m_fMusicSeconds) ); // See if there is a hold step that begins on this index. // Only do this if the noteskin cares. @@ -1117,7 +1117,7 @@ void NoteField::DrawPrimitives() m_fYReverseOffsetPixels, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT ); - bool bNoteIsUpcoming = NoteRowToBeat(q) > GAMESTATE->m_fSongBeat; + bool bNoteIsUpcoming = NoteRowToBeat(q) > m_pPlayerState->m_Position.m_fSongBeat; bAnyUpcomingInThisCol |= bNoteIsUpcoming; } diff --git a/src/Player.cpp b/src/Player.cpp index e885c2bf9c..f992b838d5 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2022,8 +2022,8 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b * "jack hammers." Hmm. */ const int iStepSearchRows = max( - BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, - iSongRow - BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds - StepSearchDistance ) ) + BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( m_pPlayerState->m_Position.m_fMusicSeconds + StepSearchDistance ) ) - iSongRow, + iSongRow - BeatToNoteRow( m_Timing->GetBeatFromElapsedTime( m_pPlayerState->m_Position.m_fMusicSeconds - StepSearchDistance ) ) ) + ROWS_PER_BEAT; int iRowOfOverlappingNoteOrRow = row; if( row == -1 ) diff --git a/src/PlayerState.cpp b/src/PlayerState.cpp index 070e96c7be..d6583059bf 100644 --- a/src/PlayerState.cpp +++ b/src/PlayerState.cpp @@ -69,8 +69,8 @@ void PlayerState::Update( float fDelta ) bool bCurrentlyEnabled = attack.bGlobal || - ( attack.fStartSecond < GAMESTATE->m_fMusicSeconds && - GAMESTATE->m_fMusicSeconds < attack.fStartSecond+attack.fSecsRemaining ); + ( attack.fStartSecond < m_Position.m_fMusicSeconds && + m_Position.m_fMusicSeconds < attack.fStartSecond+attack.fSecsRemaining ); if( m_ActiveAttacks[s].bOn == bCurrentlyEnabled ) continue; // OK @@ -116,7 +116,7 @@ void PlayerState::LaunchAttack( const Attack& a ) * so Player::Update knows to apply attack transforms correctly. (yuck) */ m_ModsToApply.push_back( attack ); if( attack.fStartSecond == -1 ) - attack.fStartSecond = GAMESTATE->m_fMusicSeconds; + attack.fStartSecond = m_Position.m_fMusicSeconds; m_ActiveAttacks.push_back( attack ); RebuildPlayerOptionsFromActiveAttacks(); From d136d19cefb7ed792be912ccba98fd626f503d63 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 08:55:50 -0500 Subject: [PATCH 045/333] fix compile; don't add features early in the morning --- src/Sprite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sprite.cpp b/src/Sprite.cpp index e34dde8802..6d0c4df7ae 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -1130,7 +1130,7 @@ public: static int setstate( T* p, lua_State *L ) { p->SetState( IArg(1) ); return 0; } static int GetState( T* p, lua_State *L ) { lua_pushnumber( L, p->GetState() ); return 1; } static int GetAnimationLengthSeconds( T* p, lua_State *L ) { lua_pushnumber( L, p->GetAnimationLengthSeconds() ); return 1; } - static int SetSecondsIntoAnimation( T* p, lua_State *L ) { p->SetSecondsIntoAnimation(FArg(0)) return 0; } + static int SetSecondsIntoAnimation( T* p, lua_State *L ) { p->SetSecondsIntoAnimation(FArg(0)); return 0; } static int SetTexture( T* p, lua_State *L ) { RageTexture *pTexture = Luna::check(L, 1); From 6b61e8e0bb5c6150bc660f84450532b50e382b58 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 09:04:44 -0500 Subject: [PATCH 046/333] fix vs2008 compile --- src/StepMania-net2008.vcproj | 234 +++++++++++++++++++++++++++++++---- 1 file changed, 211 insertions(+), 23 deletions(-) diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index d8d2058138..7d7f87a40d 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -6564,29 +6564,217 @@ RelativePath="glext.h" > - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Tue, 10 May 2011 09:11:44 -0500 Subject: [PATCH 047/333] fix script error --- Themes/_fallback/Scripts/04 Scoring.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/Scripts/04 Scoring.lua b/Themes/_fallback/Scripts/04 Scoring.lua index b6d68abb9c..1c8c8df8b5 100644 --- a/Themes/_fallback/Scripts/04 Scoring.lua +++ b/Themes/_fallback/Scripts/04 Scoring.lua @@ -8,10 +8,11 @@ local ZeroIfNotFound = { __index = function() return 0 end; }; -- Retrieve the amount of taps/holds/rolls involved. Used for some formulas. function GetTotalItems(radars) - return radars:GetValue('RadarCategory_TapsAndHolds') - + radars:GetValue('RadarCategory_Holds') - + radars:GetValue('RadarCategory_Rolls'); - + radars:GetValue('RadarCategory_Lifts'); + local total = radars:GetValue('RadarCategory_TapsAndHolds') + total = total + radars:GetValue('RadarCategory_Holds') + total = total + radars:GetValue('RadarCategory_Rolls') + total = total + radars:GetValue('RadarCategory_Lifts') + return total end; -- Determine whether marvelous timing is to be considered. From 8968ccfa45ca2280002feb05c202e5f16d0efede Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 09:13:31 -0500 Subject: [PATCH 048/333] add missing strings --- Themes/_fallback/Languages/en.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 51db471be3..d0492d5a94 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1889,6 +1889,10 @@ Modifier=Modifier Obtain an updated driver from your video card manufacturer.=Obtain an updated driver from your video card manufacturer. GLDirect was detected. GLDirect is not compatible with this game and should be disabled.=GLDirect was detected. GLDirect is not compatible with this game and should be disabled. +[RageDisplay_D3D] +DirectX 8.1 or greater is not installed. You can download it from:=DirectX 8.1 or greater is not installed. You can download it from: +Your system is reporting that Direct3D hardware acceleration is not available. Please obtain an updated driver from your video card manufacturer.=Your system is reporting that Direct3D hardware acceleration is not available. Please obtain an updated driver from your video card manufacturer. + [RageDisplay] SetVideoMode failed:=SetVideoMode failed: From 722d22dffc196ef4fe432c127ced5dae551e7c7d Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 21:21:23 +0700 Subject: [PATCH 049/333] [splittiming] temporary fix for ScreenEdit. It uses song position for now. (82) So once it builds we have to test it extensively to see where it could be wrong. --- src/ScreenEdit.cpp | 184 +++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 91 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 738c366e32..929bc974cc 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -722,8 +722,10 @@ void ScreenEdit::Init() GAMESTATE->m_bGameplayLeadIn.Set( true ); GAMESTATE->m_EditMode = EDIT_MODE.GetValue(); - GAMESTATE->m_fSongBeat = 0; - m_fTrailingBeat = GAMESTATE->m_fSongBeat; + GAMESTATE->m_Position.m_fSongBeat = 0; + FOREACH_PlayerNumber( p ) + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = 0; + m_fTrailingBeat = GAMESTATE->m_Position.m_fSongBeat; m_iShiftAnchor = -1; m_iStartPlayingAt = -1; @@ -927,12 +929,12 @@ void ScreenEdit::Update( float fDeltaTime ) continue; float fStartPlayingAtBeat = NoteRowToBeat(m_iStartPlayingAt); - if( GAMESTATE->m_fSongBeat <= fStartPlayingAtBeat ) + if( GAMESTATE->m_Position.m_fSongBeat <= fStartPlayingAtBeat ) continue; float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld; float fStartBeat = max( fStartPlayingAtBeat, m_pSteps->m_Timing.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); - float fEndBeat = max( fStartBeat, GAMESTATE->m_fSongBeat ); + float fEndBeat = max( fStartBeat, GAMESTATE->m_Position.m_fSongBeat ); fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) ); // Round start and end to the nearest snap interval @@ -981,7 +983,7 @@ void ScreenEdit::Update( float fDeltaTime ) } float fStopAtSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; - if( GAMESTATE->m_fMusicSeconds > fStopAtSeconds ) + if( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fMusicSeconds > fStopAtSeconds ) { // loop TransitionEditState( STATE_PLAYING ); @@ -994,12 +996,12 @@ void ScreenEdit::Update( float fDeltaTime ) // Update trailing beat - float fDelta = GAMESTATE->m_fSongBeat - m_fTrailingBeat; + float fDelta = GAMESTATE->m_Position.m_fSongBeat - m_fTrailingBeat; if( fabsf(fDelta) < 10 ) - fapproach( m_fTrailingBeat, GAMESTATE->m_fSongBeat, + fapproach( m_fTrailingBeat, GAMESTATE->m_Position.m_fSongBeat, fDeltaTime*40 / m_NoteFieldEdit.GetPlayerState()->m_PlayerOptions.GetCurrent().m_fScrollSpeed ); else - fapproach( m_fTrailingBeat, GAMESTATE->m_fSongBeat, + fapproach( m_fTrailingBeat, GAMESTATE->m_Position.m_fSongBeat, fabsf(fDelta) * fDeltaTime*5 ); PlayTicks(); @@ -1070,8 +1072,8 @@ void ScreenEdit::UpdateTextInfo() RString sNoteType = ssprintf( NOTES.GetValue(), NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType()).c_str() ); RString sText; - sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat ); - sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat) ); + sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_Position.m_fSongBeat ); + sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_Position.m_fSongBeat) ); switch( EDIT_MODE.GetValue() ) { DEFAULT_FAIL( EDIT_MODE.GetValue() ); @@ -1141,14 +1143,14 @@ void ScreenEdit::UpdateTextInfo() void ScreenEdit::DrawPrimitives() { // HACK: Draw using the trailing beat - float fSongBeat = GAMESTATE->m_fSongBeat; // save song beat - float fSongBeatNoOffset = GAMESTATE->m_fSongBeatNoOffset; + float fSongBeat = GAMESTATE->m_Position.m_fSongBeat; // save song beat + float fSongBeatNoOffset = GAMESTATE->m_Position.m_fSongBeatNoOffset; float fSongBeatVisible = GAMESTATE->m_fSongBeatVisible; if( !m_pSoundMusic->IsPlaying() ) { - GAMESTATE->m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect - GAMESTATE->m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect GAMESTATE->m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect } @@ -1156,8 +1158,8 @@ void ScreenEdit::DrawPrimitives() if( !m_pSoundMusic->IsPlaying() ) { - GAMESTATE->m_fSongBeat = fSongBeat; // restore real song beat - GAMESTATE->m_fSongBeatNoOffset = fSongBeatNoOffset; + GAMESTATE->m_Position.m_fSongBeat = fSongBeat; // restore real song beat + GAMESTATE->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; GAMESTATE->m_fSongBeatVisible = fSongBeatVisible; } } @@ -1243,7 +1245,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) m_iShiftAnchor = -1; return; } - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator; switch( EditB ) { @@ -1269,7 +1271,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) ShiftToRightSide( iCol, m_NoteDataEdit.GetNumTracks() ); - const float fSongBeat = GAMESTATE->m_fSongBeat; + const float fSongBeat = GAMESTATE->m_Position.m_fSongBeat; const int iSongIndex = BeatToNoteRow( fSongBeat ); if( iCol >= m_NoteDataEdit.GetNumTracks() ) // this button is not in the range of columns for this Style @@ -1407,7 +1409,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( m_PlayerStateEdit.m_PlayerOptions.GetSong().m_fScrolls[PlayerOptions::SCROLL_REVERSE] > 0.5 ) fBeatsToMove *= -1; - float fDestinationBeat = GAMESTATE->m_fSongBeat + fBeatsToMove; + float fDestinationBeat = GAMESTATE->m_Position.m_fSongBeat + fBeatsToMove; fDestinationBeat = Quantize( fDestinationBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); ScrollTo( fDestinationBeat ); @@ -1415,28 +1417,28 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_SCROLL_NEXT_MEASURE: { - float fDestinationBeat = GAMESTATE->m_fSongBeat + beatsPerMeasure; + float fDestinationBeat = GAMESTATE->m_Position.m_fSongBeat + beatsPerMeasure; fDestinationBeat = ftruncf( fDestinationBeat, (float)beatsPerMeasure ); ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_PREV_MEASURE: { - float fDestinationBeat = QuantizeUp( GAMESTATE->m_fSongBeat, (float)beatsPerMeasure ); + float fDestinationBeat = QuantizeUp( GAMESTATE->m_Position.m_fSongBeat, (float)beatsPerMeasure ); fDestinationBeat -= (float)beatsPerMeasure; ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_NEXT: { - int iRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + int iRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); NoteDataUtil::GetNextEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } break; case EDIT_BUTTON_SCROLL_PREV: { - int iRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + int iRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); NoteDataUtil::GetPrevEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } @@ -1444,13 +1446,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_LABEL_NEXT: { ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); + GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ); } break; case EDIT_BUTTON_LABEL_PREV: { ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); + GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ); } break; case EDIT_BUTTON_SNAP_NEXT: @@ -1463,11 +1465,11 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_LAY_SELECT: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iBeginMarker==-1 && m_NoteFieldEdit.m_iEndMarker==-1 ) { // lay begin marker - m_NoteFieldEdit.m_iBeginMarker = BeatToNoteRow(GAMESTATE->m_fSongBeat); + m_NoteFieldEdit.m_iBeginMarker = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); } else if( m_NoteFieldEdit.m_iEndMarker==-1 ) // only begin marker is laid { @@ -1579,7 +1581,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_BPM_UP: case EDIT_BUTTON_BPM_DOWN: { - float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_fSongBeat ); + float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat ); float fDelta; switch( EditB ) { @@ -1600,7 +1602,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } float fNewBPM = fBPM + fDelta; - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fNewBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat, fNewBPM ); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1629,7 +1631,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) break; } @@ -1637,7 +1639,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // create a new StopSegment if( fDelta > 0 ) - m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta) ); + m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), fDelta) ); } else // StopSegment being modified is m_SongTiming.m_StopSegments[i] { @@ -1675,7 +1677,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) + if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) break; } @@ -1683,7 +1685,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // create a new delay segment if( fDelta > 0 ) - m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fDelta, true) ); + m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), fDelta, true) ); } else // delay segment being modified is m_SongTiming.m_StopSegments[i] { @@ -1807,7 +1809,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) BackgroundChange bgChange; FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(g_CurrentBGChangeLayer), bgc ) { - if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat ) + if( bgc->m_fStartBeat == GAMESTATE->m_Position.m_fSongBeat ) { bAlreadyBGChangeHere = true; bgChange = *bgc; @@ -1900,7 +1902,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( pCourse == NULL ) break; CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; - float fStartTime = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + float fStartTime = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_Position.m_fSongBeat ); int iAttack = FindAttackAtTime( ce.attacks, fStartTime ); if( iAttack >= 0 ) @@ -1974,10 +1976,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) bool bAlreadyBGChangeHere = false; BackgroundLayer iLayer = BACKGROUND_LAYER_1; BackgroundChange bgChange; - bgChange.m_fStartBeat = GAMESTATE->m_fSongBeat; + bgChange.m_fStartBeat = GAMESTATE->m_Position.m_fSongBeat; FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(iLayer), bgc ) { - if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat ) + if( bgc->m_fStartBeat == GAMESTATE->m_Position.m_fSongBeat ) { bAlreadyBGChangeHere = true; bgChange = *bgc; @@ -2012,12 +2014,12 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { if( g_iDefaultRecordLength.Get() == -1 ) { - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() + 1 ); } else { - m_iStartPlayingAt = BeatToNoteRow( ftruncf(GAMESTATE->m_fSongBeat, g_iDefaultRecordLength.Get()) ); + m_iStartPlayingAt = BeatToNoteRow( ftruncf(GAMESTATE->m_Position.m_fSongBeat, g_iDefaultRecordLength.Get()) ); m_iStopPlayingAt = m_iStartPlayingAt + BeatToNoteRow( g_iDefaultRecordLength.Get() ); } @@ -2034,7 +2036,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } break; case EDIT_BUTTON_RECORD_FROM_CURSOR: - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() ); TransitionEditState( STATE_RECORDING ); break; @@ -2103,7 +2105,7 @@ void ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB ) } // Add a tap - float fBeat = GAMESTATE->m_fSongBeat; + float fBeat = GAMESTATE->m_Position.m_fSongBeat; fBeat = Quantize( fBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); const int iRow = BeatToNoteRow( fBeat ); @@ -2239,7 +2241,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB ) { case EDIT_BUTTON_RETURN_TO_EDIT: /* When exiting play mode manually, leave the cursor where it is. */ - m_fBeatToReturnTo = GAMESTATE->m_fSongBeat; + m_fBeatToReturnTo = GAMESTATE->m_Position.m_fSongBeat; TransitionEditState( STATE_EDITING ); break; case EDIT_BUTTON_OFFSET_UP: @@ -2310,7 +2312,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_EDITING: // If exiting EDIT mode, save the cursor position. - m_fBeatToReturnTo = GAMESTATE->m_fSongBeat; + m_fBeatToReturnTo = GAMESTATE->m_Position.m_fSongBeat; break; case STATE_PLAYING: @@ -2363,14 +2365,14 @@ void ScreenEdit::TransitionEditState( EditState em ) m_Foreground.Unload(); // Restore the cursor position. - GAMESTATE->m_fSongBeat = m_fBeatToReturnTo; + GAMESTATE->m_Position.m_fSongBeat = m_fBeatToReturnTo; // Make sure we're snapped. - GAMESTATE->m_fSongBeat = Quantize( GAMESTATE->m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); + GAMESTATE->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); /* Playing and recording have lead-ins, which may start before beat 0; * make sure we don't stay there if we escaped out early. */ - GAMESTATE->m_fSongBeat = max( GAMESTATE->m_fSongBeat, 0 ); + GAMESTATE->m_Position.m_fSongBeat = max( GAMESTATE->m_Position.m_fSongBeat, 0 ); break; @@ -2463,7 +2465,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_PLAYING: case STATE_RECORDING: - const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); + const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_Position.m_fSongBeat); LOG->Trace( "Starting playback at %f", fStartSeconds ); RageSoundParams p; @@ -2483,11 +2485,11 @@ void ScreenEdit::ScrollTo( float fDestinationBeat ) CLAMP( fDestinationBeat, 0, GetMaximumBeatForMoving() ); // Don't play the sound and do the hold note logic below if our position didn't change. - const float fOriginalBeat = GAMESTATE->m_fSongBeat; + const float fOriginalBeat = GAMESTATE->m_Position.m_fSongBeat; if( fOriginalBeat == fDestinationBeat ) return; - GAMESTATE->m_fSongBeat = fDestinationBeat; + GAMESTATE->m_Position.m_fSongBeat = fDestinationBeat; // check to see if they're holding a button for( int n=0; n 0 ) - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_fSongBeat, fBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat, fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fStop ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, fDelay, true ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2649,7 +2651,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = atoi( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); + m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_Position.m_fSongBeat, iNum ); } SetDirty( true ); } @@ -2658,7 +2660,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = atoi( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); + m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_Position.m_fSongBeat, iDen ); } SetDirty( true ); } @@ -2667,7 +2669,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); + m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_Position.m_fSongBeat, iTick ); } SetDirty( true ); } @@ -2676,7 +2678,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); + m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_Position.m_fSongBeat, iCombo ); } SetDirty( true ); } @@ -2687,14 +2689,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); + m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_Position.m_fSongBeat, sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); + m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_Position.m_fSongBeat, fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -2745,7 +2747,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { PlayerOptions poChosen = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetPreferred(); RString sMods = poChosen.GetString(); - const int row = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + const int row = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); TapNote tn( TapNote::attack, @@ -2767,7 +2769,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; int iAttack; - g_fLastInsertAttackPositionSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_fSongBeat ); + g_fLastInsertAttackPositionSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_Position.m_fSongBeat ); g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] ); iAttack = FindAttackAtTime( ce.attacks, g_fLastInsertAttackPositionSeconds ); @@ -2922,12 +2924,12 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { /* When another screen comes up, RageSounds takes over the sound timer. When we come * back, put the timer back to where it was. */ - GAMESTATE->m_fSongBeat = m_fTrailingBeat; + GAMESTATE->m_Position.m_fSongBeat = m_fTrailingBeat; } else if( SM == SM_LoseFocus ) { // Snap the trailing beat, in case we lose focus while tweening. - m_fTrailingBeat = GAMESTATE->m_fSongBeat; + m_fTrailingBeat = GAMESTATE->m_Position.m_fSongBeat; } ScreenWithMenuElements::HandleScreenMessage( SM ); @@ -2938,10 +2940,10 @@ void ScreenEdit::OnSnapModeChange() m_soundChangeSnap.Play(); NoteType nt = m_SnapDisplay.GetNoteType(); - int iStepIndex = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + int iStepIndex = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); int iElementsPerNoteType = BeatToNoteRow( NoteTypeToBeat(nt) ); int iStepIndexHangover = iStepIndex % iElementsPerNoteType; - GAMESTATE->m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); + GAMESTATE->m_Position.m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); } @@ -3088,14 +3090,14 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case play_current_beat_to_end: { - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() ); TransitionEditState( STATE_PLAYING ); } break; case set_selection_start: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iEndMarker!=-1 && iCurrentRow >= m_NoteFieldEdit.m_iEndMarker ) { SCREENMAN->PlayInvalidSound(); @@ -3109,7 +3111,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case set_selection_end: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iBeginMarker!=-1 && iCurrentRow <= m_NoteFieldEdit.m_iBeginMarker ) { SCREENMAN->PlayInvalidSound(); @@ -3256,7 +3258,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns case edit_timing_data: { TimingData pTime = m_pSteps->m_Timing; - const float fBeat = pTime.GetBeatFromElapsedTime(GAMESTATE->m_fMusicSeconds); + const float fBeat = GAMESTATE->m_Position.m_fSongBeat; g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); @@ -3361,7 +3363,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns { DEFAULT_FAIL( c ); case paste_at_current_beat: - iDestFirstRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + iDestFirstRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); break; case paste_at_begin_marker: ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 ); @@ -3539,16 +3541,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns TransitionEditState( STATE_RECORDING ); break; case insert_and_shift: - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case delete_and_shift: - NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_forward: - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_backward: - m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case convert_to_pause: { @@ -3576,14 +3578,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_pause_to_beat: { // TODO: Convert both Delays and Stops at once. - float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ); - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_fSongBeat, 0 ); + float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, 0 ); - float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_fSongBeat) / 60; + float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_Position.m_fSongBeat) / 60; // don't move the step from where it is, just move everything later - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: @@ -3749,7 +3751,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_fSongBeat) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_Position.m_fSongBeat) ), 10 ); break; @@ -3757,7 +3759,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromStopChange, ENTER_STOP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -3765,7 +3767,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromDelayChange, ENTER_DELAY_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -3773,7 +3775,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureNumeratorChange, ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator ), 3 ); break; @@ -3781,7 +3783,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureDenominatorChange, ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iDenominator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iDenominator ), 3 ); break; @@ -3789,7 +3791,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTickcountChange, ENTER_TICKCOUNT_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ), 2 ); break; @@ -3797,7 +3799,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromComboChange, ENTER_COMBO_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ), 4 ); break; @@ -3805,7 +3807,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromLabelChange, ENTER_LABEL_VALUE, - ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), + ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_Position.m_fSongBeat ).c_str() ), 64 ); break; @@ -3813,7 +3815,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -3826,7 +3828,7 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector &iAns FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(g_CurrentBGChangeLayer), iter ) { - if( iter->m_fStartBeat == GAMESTATE->m_fSongBeat ) + if( iter->m_fStartBeat == GAMESTATE->m_Position.m_fSongBeat ) { newChange = *iter; // delete the old change. We'll add a new one below. @@ -3835,7 +3837,7 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector &iAns } } - newChange.m_fStartBeat = GAMESTATE->m_fSongBeat; + newChange.m_fStartBeat = GAMESTATE->m_Position.m_fSongBeat; newChange.m_fRate = StringToFloat( g_BackgroundChange.rows[rate].choices[iAnswers[rate]] )/100.f; newChange.m_sTransition = iAnswers[transition] ? g_BackgroundChange.rows[transition].choices[iAnswers[transition]] : RString(); newChange.m_def.m_sEffect = iAnswers[effect] ? g_BackgroundChange.rows[effect].choices[iAnswers[effect]] : RString(); @@ -4020,7 +4022,7 @@ void ScreenEdit::CheckNumberOfNotesAndUndo() if( EDIT_MODE.GetValue() != EditMode_Home ) return; - TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ); + TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ); int rowsPerMeasure = curTime.m_iDenominator * curTime.m_iNumerator; for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure ) @@ -4072,7 +4074,7 @@ float ScreenEdit::GetMaximumBeatForNewNote() const /* Round up to the next measure end. Some songs end on weird beats * mid-measure, and it's odd to have movement capped to these weird * beats. */ - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator; fEndBeat += beatsPerMeasure; fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure ); From b8a4521f9cdfc7e887dc66d35370fbfddfaf7ecb Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 21:22:01 +0700 Subject: [PATCH 050/333] Move the reset code to SongPosition. --- src/GameState.cpp | 15 +++++---------- src/NoteField.cpp | 2 +- src/SongPosition.cpp | 16 ++++++++++++++++ src/SongPosition.h | 1 + 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 9ad930dcd3..4df8259744 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -893,22 +893,17 @@ const float GameState::MUSIC_SECONDS_INVALID = -5000.0f; void GameState::ResetMusicStatistics() { - m_fMusicSeconds = 0; // MUSIC_SECONDS_INVALID; - // todo: move me to FOREACH_EnabledPlayer( p ) after [NUM_PLAYERS]ing - m_fSongBeat = 0; - m_fSongBeatNoOffset = 0; - m_fCurBPS = 10; - //m_bStop = false; - m_bFreeze = false; - m_bDelay = false; - m_iWarpBeginRow = -1; // Set to -1 because some song may want to warp to row 0. -aj - m_fWarpDestination = -1; // Set when a warp is encountered. also see above. -aj + m_Position.Reset(); + m_fMusicSecondsVisible = 0; m_fSongBeatVisible = 0; Actor::SetBGMTime( 0, 0, 0, 0 ); FOREACH_PlayerNumber( p ) + { m_pPlayerState[p]->ClearHopoState(); + m_pPlayerState[p]->m_Position.Reset(); + } } void GameState::ResetStageStatistics() diff --git a/src/NoteField.cpp b/src/NoteField.cpp index c4c6826765..72a9ceb90e 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -618,7 +618,7 @@ float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistance bBoomerang = (fAccels[PlayerOptions::ACCEL_BOOMERANG] != 0); } - while( fFirstBeatToDraw < m_pPlayerState->m_Position.m_fSongBeat ) + while( fFirstBeatToDraw < pPlayerState->m_Position.m_fSongBeat ) { bool bIsPastPeakYOffset; float fPeakYOffset; diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 1a68e620a6..14a67c1806 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -46,6 +46,22 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData } +void SongPosition::Reset() +{ + + m_fMusicSeconds = 0; // MUSIC_SECONDS_INVALID; + // todo: move me to FOREACH_EnabledPlayer( p ) after [NUM_PLAYERS]ing + m_fSongBeat = 0; + m_fSongBeatNoOffset = 0; + m_fCurBPS = 10; + //m_bStop = false; + m_bFreeze = false; + m_bDelay = false; + m_iWarpBeginRow = -1; // Set to -1 because some song may want to warp to row 0. -aj + m_fWarpDestination = -1; // Set when a warp is encountered. also see above. -aj + +} + /** * @file * @author Thai Pangsakulyanont (c) 2011 diff --git a/src/SongPosition.h b/src/SongPosition.h index 97d2d6fd3c..abe1dc2a8e 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -32,6 +32,7 @@ class SongPosition float m_fWarpDestination; RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update + void Reset(); void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); }; From a867b886400ef7706aa31a667a783823b50529d5 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 09:24:31 -0500 Subject: [PATCH 051/333] add missing endless banner --- Themes/_fallback/Graphics/Banner Endless.redir | 1 + src/BPMDisplay.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Themes/_fallback/Graphics/Banner Endless.redir diff --git a/Themes/_fallback/Graphics/Banner Endless.redir b/Themes/_fallback/Graphics/Banner Endless.redir new file mode 100644 index 0000000000..507050cda9 --- /dev/null +++ b/Themes/_fallback/Graphics/Banner Endless.redir @@ -0,0 +1 @@ +Common fallback banner \ No newline at end of file diff --git a/src/BPMDisplay.cpp b/src/BPMDisplay.cpp index 5bdcbd66f4..4412ee9bcd 100644 --- a/src/BPMDisplay.cpp +++ b/src/BPMDisplay.cpp @@ -204,7 +204,8 @@ void BPMDisplay::SetBpmFromCourse( const Course* pCourse ) StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; Trail *pTrail = pCourse->GetTrail( st ); - ASSERT( pTrail ); + // GetTranslitFullTitle because "Crashinfo.txt is garbled because of the ANSI output as usual." -f + ASSERT_M( pTrail, ssprintf("Course '%s' has no trail for StepsType '%s'", pCourse->GetTranslitFullTitle(), StringConversion::ToString(st).c_str() ) ); m_fCycleTime = 0.2f; From ce392f003cd9bd1b461cb78cff0f6a9d252cd2fb Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 09:30:03 -0500 Subject: [PATCH 052/333] [BPMDisplay] Added SetFromCourse Lua binding. --- Docs/Changelog_sm5.txt | 3 ++- src/BPMDisplay.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 2addb23d65..d6320fef24 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -10,7 +10,8 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/10 ---------- -* [Sprite] Added SetSecondsIntoAnimation(float) Lua binding. [AJ] +* [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] +* [BPMDisplay] Added SetFromCourse Lua binding. [AJ] 2011/05/03 ---------- diff --git a/src/BPMDisplay.cpp b/src/BPMDisplay.cpp index 4412ee9bcd..981976974f 100644 --- a/src/BPMDisplay.cpp +++ b/src/BPMDisplay.cpp @@ -305,12 +305,23 @@ public: } return 0; } + static int SetFromCourse( T* p, lua_State *L ) + { + if( lua_isnil(L,1) ) { p->NoBPM(); } + else + { + const Course* pCourse = Luna::check( L, 1, true ); + p->SetBpmFromCourse(pCourse); + } + return 0; + } static int GetText( T* p, lua_State *L ) { lua_pushstring( L, p->GetText() ); return 1; } LunaBPMDisplay() { ADD_METHOD( SetFromGameState ); ADD_METHOD( SetFromSong ); + ADD_METHOD( SetFromCourse ); ADD_METHOD( GetText ); } }; From 2c87c34899772f14199456cc23c4250f7295fdc4 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 10 May 2011 21:44:25 +0700 Subject: [PATCH 053/333] [splittiming] ArrowEffects, BPMDisplay, Inventory, MeterDisplay --- src/ArrowEffects.cpp | 30 +++++++++++++++++------------- src/BPMDisplay.cpp | 2 +- src/Inventory.cpp | 2 +- src/MeterDisplay.cpp | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index ffb21ae3d8..69372078cd 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -67,13 +67,13 @@ static float GetNoteFieldHeight( const PlayerState* pPlayerState ) namespace { - float g_fExpandSeconds = 0; struct PerPlayerData { float m_fMinTornadoX[MAX_COLS_PER_PLAYER]; float m_fMaxTornadoX[MAX_COLS_PER_PLAYER]; float m_fInvertDistance[MAX_COLS_PER_PLAYER]; float m_fBeatFactor; + float m_fExpandSeconds; }; PerPlayerData g_EffectData[NUM_PLAYERS]; }; @@ -82,22 +82,23 @@ void ArrowEffects::Update() { const Style* pStyle = GAMESTATE->GetCurrentStyle(); - { - static float fLastTime = 0; - float fTime = RageTimer::GetTimeSinceStartFast(); - if( !GAMESTATE->m_bFreeze || !GAMESTATE->m_bDelay ) - { - g_fExpandSeconds += fTime - fLastTime; - g_fExpandSeconds = fmodf( g_fExpandSeconds, PI*2 ); - } - fLastTime = fTime; - } - FOREACH_PlayerNumber( pn ) { const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; PerPlayerData &data = g_EffectData[pn]; + + { + static float fLastTime = 0; + float fTime = RageTimer::GetTimeSinceStartFast(); + if( !GAMESTATE->m_pPlayerState[pn]->m_Position.m_bFreeze || !GAMESTATE->m_pPlayerState[pn]->m_Position.m_bDelay ) + { + data.m_fExpandSeconds += fTime - fLastTime; + data.m_fExpandSeconds = fmodf( data.m_fExpandSeconds, PI*2 ); + } + fLastTime = fTime; + } + // Update Tornado for( int iColNum = 0; iColNum < MAX_COLS_PER_PLAYER; ++iColNum ) { @@ -307,7 +308,10 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( fAccels[PlayerOptions::ACCEL_EXPAND] != 0 ) { - float fExpandMultiplier = SCALE( RageFastCos(g_fExpandSeconds*EXPAND_MULTIPLIER_FREQUENCY), + // TODO: Don't index by PlayerNumber. + PerPlayerData &data = g_EffectData[pPlayerState->m_PlayerNumber]; + + float fExpandMultiplier = SCALE( RageFastCos(data.m_fExpandSeconds*EXPAND_MULTIPLIER_FREQUENCY), EXPAND_MULTIPLIER_SCALE_FROM_LOW, EXPAND_MULTIPLIER_SCALE_FROM_HIGH, EXPAND_MULTIPLIER_SCALE_TO_LOW, EXPAND_MULTIPLIER_SCALE_TO_HIGH ); fScrollSpeed *= SCALE( fAccels[PlayerOptions::ACCEL_EXPAND], diff --git a/src/BPMDisplay.cpp b/src/BPMDisplay.cpp index 5bdcbd66f4..bf4b8b15c2 100644 --- a/src/BPMDisplay.cpp +++ b/src/BPMDisplay.cpp @@ -276,7 +276,7 @@ SongBPMDisplay::SongBPMDisplay() void SongBPMDisplay::Update( float fDeltaTime ) { - float fGameStateBPM = GAMESTATE->m_fCurBPS * 60.0f; + float fGameStateBPM = GAMESTATE->m_Position.m_fCurBPS * 60.0f; if( m_fLastGameStateBPM != fGameStateBPM ) { m_fLastGameStateBPM = fGameStateBPM; diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 0c0291696d..3b7eb88b32 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -121,7 +121,7 @@ void Inventory::Update( float fDelta ) // use items if this player is CPU-controlled if( m_pPlayerState->m_PlayerController != PC_HUMAN && - GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) { // every 1 seconds, try to use an item int iLastSecond = (int)(RageTimer::GetTimeSinceStartFast() - fDelta); diff --git a/src/MeterDisplay.cpp b/src/MeterDisplay.cpp index 66c0b19587..641b50d73c 100644 --- a/src/MeterDisplay.cpp +++ b/src/MeterDisplay.cpp @@ -75,7 +75,7 @@ void SongMeterDisplay::Update( float fDeltaTime ) { float fSongStartSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat ); float fSongEndSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); - float fPercentPositionSong = SCALE( GAMESTATE->m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f ); + float fPercentPositionSong = SCALE( GAMESTATE->m_Position.m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f ); CLAMP( fPercentPositionSong, 0, 1 ); SetPercent( fPercentPositionSong ); From 7fa6620423e0568e785ed14e380f047ab621fd31 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 14:45:52 -0400 Subject: [PATCH 054/333] [splittiming] m_Position needed. (50) --- src/Attack.cpp | 2 +- src/Background.cpp | 4 ++-- src/DancingCharacters.cpp | 14 +++++++------- src/Foreground.cpp | 10 +++++----- src/LightsManager.cpp | 6 +++--- src/LyricDisplay.cpp | 6 +++--- src/ScreenNameEntry.cpp | 4 ++-- src/ScreenSyncOverlay.cpp | 2 +- src/SoundEffectControl.cpp | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Attack.cpp b/src/Attack.cpp index 1a67cc3181..1bf2c8623b 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -32,7 +32,7 @@ void Attack::GetRealtimeAttackBeats( const Song *pSong, const PlayerState* pPlay ASSERT( pSong ); /* If reasonable, push the attack forward 8 beats so that notes on screen don't change suddenly. */ - fStartBeat = min( GAMESTATE->m_fSongBeat+8, pPlayerState->m_fLastDrawnBeat ); + fStartBeat = min( GAMESTATE->m_Position.m_fSongBeat+8, pPlayerState->m_fLastDrawnBeat ); fStartBeat = truncf(fStartBeat)+1; const TimingData &timing = pSong->m_SongTiming; diff --git a/src/Background.cpp b/src/Background.cpp index 5047e5fc1e..8c5a64c5fa 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -800,9 +800,9 @@ void BackgroundImpl::Update( float fDeltaTime ) FOREACH_BackgroundLayer( i ) { Layer &layer = m_Layer[i]; - layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_fMusicSeconds, m_mapNameToTransition ); + layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_Position.m_fMusicSeconds, m_mapNameToTransition ); } - m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds; + m_fLastMusicSeconds = GAMESTATE->m_Position.m_fMusicSeconds; } void BackgroundImpl::DrawPrimitives() diff --git a/src/DancingCharacters.cpp b/src/DancingCharacters.cpp index 6653173f9b..8b5be828c3 100644 --- a/src/DancingCharacters.cpp +++ b/src/DancingCharacters.cpp @@ -175,7 +175,7 @@ int Neg1OrPos1() { return RandomInt( 2 ) ? -1 : +1; } void DancingCharacters::Update( float fDelta ) { - if( GAMESTATE->m_bFreeze || GAMESTATE->m_bDelay ) + if( GAMESTATE->m_Position.m_bFreeze || GAMESTATE->m_Position.m_bDelay ) { // spin the camera Matrix-style m_CameraPanYStart += fDelta*40; @@ -184,7 +184,7 @@ void DancingCharacters::Update( float fDelta ) else { // make the characters move - float fBPM = GAMESTATE->m_fCurBPS*60; + float fBPM = GAMESTATE->m_Position.m_fCurBPS*60; float fUpdateScale = SCALE( fBPM, 60.f, 300.f, 0.75f, 1.5f ); CLAMP( fUpdateScale, 0.75f, 1.5f ); @@ -209,8 +209,8 @@ void DancingCharacters::Update( float fDelta ) } bWasGameplayStarting = bGameplayStarting; - static float fLastBeat = GAMESTATE->m_fSongBeat; - float fThisBeat = GAMESTATE->m_fSongBeat; + static float fLastBeat = GAMESTATE->m_Position.m_fSongBeat; + float fThisBeat = GAMESTATE->m_Position.m_fSongBeat; if( fLastBeat < GAMESTATE->m_pCurSong->m_fFirstBeat && fThisBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat ) { @@ -220,7 +220,7 @@ void DancingCharacters::Update( float fDelta ) fLastBeat = fThisBeat; // time for a new sweep? - if( GAMESTATE->m_fSongBeat > m_fThisCameraEndBeat ) + if( GAMESTATE->m_Position.m_fSongBeat > m_fThisCameraEndBeat ) { if( RandomInt(6) >= 4 ) { @@ -248,7 +248,7 @@ void DancingCharacters::Update( float fDelta ) m_fLookAtHeight = CAMERA_STILL_LOOK_AT_HEIGHT; } - int iCurBeat = (int)GAMESTATE->m_fSongBeat; + int iCurBeat = (int)GAMESTATE->m_Position.m_fSongBeat; iCurBeat -= iCurBeat%8; m_fThisCameraStartBeat = (float) iCurBeat; @@ -313,7 +313,7 @@ void DancingCharacters::DrawPrimitives() if(m_fThisCameraStartBeat == m_fThisCameraEndBeat) fPercentIntoSweep = 0; else - fPercentIntoSweep = SCALE(GAMESTATE->m_fSongBeat, m_fThisCameraStartBeat, m_fThisCameraEndBeat, 0.f, 1.f ); + fPercentIntoSweep = SCALE(GAMESTATE->m_Position.m_fSongBeat, m_fThisCameraStartBeat, m_fThisCameraEndBeat, 0.f, 1.f ); float fCameraPanY = SCALE( fPercentIntoSweep, 0.f, 1.f, m_CameraPanYStart, m_CameraPanYEnd ); float fCameraHeight = SCALE( fPercentIntoSweep, 0.f, 1.f, m_fCameraHeightStart, m_fCameraHeightEnd ); diff --git a/src/Foreground.cpp b/src/Foreground.cpp index 54ba873d7e..f7b7307b37 100644 --- a/src/Foreground.cpp +++ b/src/Foreground.cpp @@ -65,7 +65,7 @@ void Foreground::Update( float fDeltaTime ) { LoadedBGA &bga = m_BGAnimations[i]; - if( GAMESTATE->m_fSongBeat < bga.m_fStartBeat ) + if( GAMESTATE->m_Position.m_fSongBeat < bga.m_fStartBeat ) { // The animation hasn't started yet. continue; @@ -83,11 +83,11 @@ void Foreground::Update( float fDeltaTime ) bga.m_bga->PlayCommand( "On" ); const float fStartSecond = m_pSong->m_SongTiming.GetElapsedTimeFromBeat( bga.m_fStartBeat ); - lDeltaTime = GAMESTATE->m_fMusicSeconds - fStartSecond; + lDeltaTime = GAMESTATE->m_Position.m_fMusicSeconds - fStartSecond; } else { - lDeltaTime = GAMESTATE->m_fMusicSeconds - m_fLastMusicSeconds; + lDeltaTime = GAMESTATE->m_Position.m_fMusicSeconds - m_fLastMusicSeconds; } // This shouldn't go down, but be safe: @@ -95,7 +95,7 @@ void Foreground::Update( float fDeltaTime ) bga.m_bga->Update( lDeltaTime / fRate ); - if( GAMESTATE->m_fSongBeat > bga.m_fStopBeat ) + if( GAMESTATE->m_Position.m_fSongBeat > bga.m_fStopBeat ) { // Finished. bga.m_bga->SetVisible( false ); @@ -104,7 +104,7 @@ void Foreground::Update( float fDeltaTime ) } } - m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds; + m_fLastMusicSeconds = GAMESTATE->m_Position.m_fMusicSeconds; } /* diff --git a/src/LightsManager.cpp b/src/LightsManager.cpp index b3f05c585b..54e220bf07 100644 --- a/src/LightsManager.cpp +++ b/src/LightsManager.cpp @@ -230,12 +230,12 @@ void LightsManager::Update( float fDeltaTime ) static float fLastBeat; static int iLight; - if( fracf(GAMESTATE->m_fLightSongBeat) < fracf(fLastBeat) ) + if( fracf(GAMESTATE->m_Position.m_fLightSongBeat) < fracf(fLastBeat) ) { ++iLight; wrap( iLight, 4 ); } - fLastBeat = GAMESTATE->m_fLightSongBeat; + fLastBeat = GAMESTATE->m_Position.m_fLightSongBeat; switch( iLight ) { case 0: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT] = true; break; @@ -405,7 +405,7 @@ void LightsManager::Update( float fDeltaTime ) // If not joined, has enough credits, and not too late to join, then // blink the menu buttons rapidly so they'll press Start { - int iBeat = (int)(GAMESTATE->m_fLightSongBeat*4); + int iBeat = (int)(GAMESTATE->m_Position.m_fLightSongBeat*4); bool bBlinkOn = (iBeat%2)==0; FOREACH_PlayerNumber( pn ) { diff --git a/src/LyricDisplay.cpp b/src/LyricDisplay.cpp index fec9827e34..7284d2dc17 100644 --- a/src/LyricDisplay.cpp +++ b/src/LyricDisplay.cpp @@ -41,9 +41,9 @@ void LyricDisplay::Update( float fDeltaTime ) return; // If the song has changed (in a course), reset. - if( GAMESTATE->m_fMusicSeconds < m_fLastSecond ) + if( GAMESTATE->m_Position.m_fMusicSeconds < m_fLastSecond ) Init(); - m_fLastSecond = GAMESTATE->m_fMusicSeconds; + m_fLastSecond = GAMESTATE->m_Position.m_fMusicSeconds; if( m_iCurLyricNumber >= GAMESTATE->m_pCurSong->m_LyricSegments.size() ) return; @@ -51,7 +51,7 @@ void LyricDisplay::Update( float fDeltaTime ) const Song *pSong = GAMESTATE->m_pCurSong; const float fStartTime = (pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime) - IN_LENGTH.GetValue(); - if( GAMESTATE->m_fMusicSeconds < fStartTime ) + if( GAMESTATE->m_Position.m_fMusicSeconds < fStartTime ) return; // Clamp this lyric to the beginning of the next or the end of the music. diff --git a/src/ScreenNameEntry.cpp b/src/ScreenNameEntry.cpp index fca92a59b1..b4eeeed4cc 100644 --- a/src/ScreenNameEntry.cpp +++ b/src/ScreenNameEntry.cpp @@ -61,7 +61,7 @@ void ScreenNameEntry::ScrollingText::Init( const RString &sName, const vectorm_fSongBeat; + const float fFakeBeat = GAMESTATE->m_Position.m_fSongBeat; const size_t iClosestIndex = lrintf( fFakeBeat ) % CHARS_CHOICES.size(); const float fClosestYOffset = GetClosestCharYOffset( fFakeBeat ); @@ -325,7 +325,7 @@ void ScreenNameEntry::Update( float fDelta ) SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("name entry") ); m_fFakeBeat += fDelta * FAKE_BEATS_PER_SEC; - GAMESTATE->m_fSongBeat = m_fFakeBeat; + GAMESTATE->m_Position.m_fSongBeat = m_fFakeBeat; ScreenWithMenuElements::Update(fDelta); } diff --git a/src/ScreenSyncOverlay.cpp b/src/ScreenSyncOverlay.cpp index baf240d54d..5f5d8e37f4 100644 --- a/src/ScreenSyncOverlay.cpp +++ b/src/ScreenSyncOverlay.cpp @@ -221,7 +221,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input ) } if( GAMESTATE->m_pCurSong != NULL ) { - BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat ); + BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ); seg.m_fBPS += fDelta; } } diff --git a/src/SoundEffectControl.cpp b/src/SoundEffectControl.cpp index 40d21fa6ba..2055e6bda1 100644 --- a/src/SoundEffectControl.cpp +++ b/src/SoundEffectControl.cpp @@ -44,7 +44,7 @@ void SoundEffectControl::Update( float fDeltaTime ) if( LOCK_TO_HOLD ) { - int iRow = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + int iRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); int iHoldsHeld, iHoldsLetGo; HoldsBeingHeld( iRow, iHoldsHeld, iHoldsLetGo ); From fb8b387fb7b8dd3ce60e77e9415b1e9a357e534c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 14:53:59 -0400 Subject: [PATCH 055/333] [splittiming] Compiles and links. Not guaranteed to work. Adjustments to GameState and SongPosition may still be needed. --- src/BeginnerHelper.cpp | 16 ++++++++-------- src/GameSoundManager.cpp | 24 ++++++++++++------------ src/GameState.cpp | 12 ++++++------ src/GameplayAssist.cpp | 10 +++++----- src/ScreenGameplay.cpp | 24 ++++++++++++------------ src/ScreenHowToPlay.cpp | 10 +++++----- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/BeginnerHelper.cpp b/src/BeginnerHelper.cpp index 3bf23107df..9bc73247ba 100644 --- a/src/BeginnerHelper.cpp +++ b/src/BeginnerHelper.cpp @@ -191,7 +191,7 @@ void BeginnerHelper::ShowStepCircle( PlayerNumber pn, int CSTEP ) m_sStepCircle[pn][isc].StopEffect(); m_sStepCircle[pn][isc].SetZoom( 2 ); m_sStepCircle[pn][isc].StopTweening(); - m_sStepCircle[pn][isc].BeginTweening( GAMESTATE->m_fCurBPS/3, TWEEN_LINEAR ); + m_sStepCircle[pn][isc].BeginTweening( GAMESTATE->m_Position.m_fCurBPS/3, TWEEN_LINEAR ); m_sStepCircle[pn][isc].SetZoom( 0 ); } @@ -318,19 +318,19 @@ void BeginnerHelper::Step( PlayerNumber pn, int CSTEP ) ShowStepCircle( pn, ST_DOWN ); m_pDancer[pn]->StopTweening(); m_pDancer[pn]->PlayAnimation( "Step-JUMPLR", 1.5f ); - m_pDancer[pn]->BeginTweening( GAMESTATE->m_fCurBPS/8, TWEEN_LINEAR ); + m_pDancer[pn]->BeginTweening( GAMESTATE->m_Position.m_fCurBPS/8, TWEEN_LINEAR ); m_pDancer[pn]->SetRotationY( 90 ); - m_pDancer[pn]->BeginTweening( 1/(GAMESTATE->m_fCurBPS * 2) ); //sleep between jump-frames - m_pDancer[pn]->BeginTweening( GAMESTATE->m_fCurBPS /6, TWEEN_LINEAR ); + m_pDancer[pn]->BeginTweening( 1/(GAMESTATE->m_Position.m_fCurBPS * 2) ); //sleep between jump-frames + m_pDancer[pn]->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /6, TWEEN_LINEAR ); m_pDancer[pn]->SetRotationY( 0 ); break; } m_sFlash.StopEffect(); m_sFlash.StopTweening(); - m_sFlash.Sleep( GAMESTATE->m_fCurBPS/16 ); + m_sFlash.Sleep( GAMESTATE->m_Position.m_fCurBPS/16 ); m_sFlash.SetDiffuseAlpha( 1 ); - m_sFlash.BeginTweening( 1/GAMESTATE->m_fCurBPS * 0.5f ); + m_sFlash.BeginTweening( 1/GAMESTATE->m_Position.m_fCurBPS * 0.5f ); m_sFlash.SetDiffuseAlpha( 0 ); } @@ -340,7 +340,7 @@ void BeginnerHelper::Update( float fDeltaTime ) return; // the row we want to check on this update - int iCurRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat + 0.4f ); + int iCurRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat + 0.4f ); FOREACH_EnabledPlayer( pn ) { for( int iRow=m_iLastRowChecked; iRowUpdate( fDeltaTime ); m_sFlash.Update( fDeltaTime ); - float beat = fDeltaTime*GAMESTATE->m_fCurBPS; + float beat = fDeltaTime*GAMESTATE->m_Position.m_fCurBPS; // If this is not a human player, the dancer is not shown FOREACH_HumanPlayer( pu ) { diff --git a/src/GameSoundManager.cpp b/src/GameSoundManager.cpp index 6e517249fb..9560dfb4b3 100644 --- a/src/GameSoundManager.cpp +++ b/src/GameSoundManager.cpp @@ -201,7 +201,7 @@ static void StartMusic( MusicToPlay &ToPlay ) { /* This song has no real timing data. The offset is arbitrary. Change it so * the beat will line up to where we are now, so we don't have to delay. */ - float fDestBeat = fmodfp( GAMESTATE->m_fSongBeatNoOffset, 1 ); + float fDestBeat = fmodfp( GAMESTATE->m_Position.m_fSongBeatNoOffset, 1 ); float fTime = NewMusic->m_NewTiming.GetElapsedTimeFromBeatNoOffset( fDestBeat ); NewMusic->m_NewTiming.m_fBeat0OffsetInSeconds = fTime; @@ -223,7 +223,7 @@ static void StartMusic( MusicToPlay &ToPlay ) * common when starting a precached sound, but our sound isn't, so it'll * probably take a little longer. Nudge the latency up. */ const float fPresumedLatency = SOUNDMAN->GetPlayLatency() + 0.040f; - const float fCurSecond = GAMESTATE->m_fMusicSeconds + fPresumedLatency; + const float fCurSecond = GAMESTATE->m_Position.m_fMusicSeconds + fPresumedLatency; const float fCurBeat = g_Playing->m_Timing.GetBeatFromElapsedTimeNoOffset( fCurSecond ); /* The beat that the new sound will start on. */ @@ -236,9 +236,9 @@ static void StartMusic( MusicToPlay &ToPlay ) const float fSecondToStartOn = g_Playing->m_Timing.GetElapsedTimeFromBeatNoOffset( fCurBeatToStartOn ); const float fMaximumDistance = 2; - const float fDistance = min( fSecondToStartOn - GAMESTATE->m_fMusicSeconds, fMaximumDistance ); + const float fDistance = min( fSecondToStartOn - GAMESTATE->m_Position.m_fMusicSeconds, fMaximumDistance ); - when = GAMESTATE->m_LastBeatUpdate + fDistance; + when = GAMESTATE->m_Position.m_LastBeatUpdate + fDistance; } /* Important: don't hold the mutex while we load and seek the actual sound. */ @@ -552,8 +552,8 @@ void GameSoundManager::Update( float fDeltaTime ) if( !g_Playing->m_Music->IsPlaying() ) { /* There's no song playing. Fake it. */ - CHECKPOINT_M( ssprintf("%f, delta %f", GAMESTATE->m_fMusicSeconds, fDeltaTime) ); - GAMESTATE->UpdateSongPosition( GAMESTATE->m_fMusicSeconds + fDeltaTime, g_Playing->m_Timing ); + CHECKPOINT_M( ssprintf("%f, delta %f", GAMESTATE->m_Position.m_fMusicSeconds, fDeltaTime) ); + GAMESTATE->UpdateSongPosition( GAMESTATE->m_Position.m_fMusicSeconds + fDeltaTime, g_Playing->m_Timing ); return; } @@ -570,8 +570,8 @@ void GameSoundManager::Update( float fDeltaTime ) // if( PREFSMAN->m_bLogSkips && !g_Playing->m_bTimingDelayed ) { - const float fExpectedTimePassed = (tm - GAMESTATE->m_LastBeatUpdate) * g_Playing->m_Music->GetPlaybackRate(); - const float fSoundTimePassed = fSeconds - GAMESTATE->m_fMusicSeconds; + const float fExpectedTimePassed = (tm - GAMESTATE->m_Position.m_LastBeatUpdate) * g_Playing->m_Music->GetPlaybackRate(); + const float fSoundTimePassed = fSeconds - GAMESTATE->m_Position.m_fMusicSeconds; const float fDiff = fExpectedTimePassed - fSoundTimePassed; static RString sLastFile = ""; @@ -580,7 +580,7 @@ void GameSoundManager::Update( float fDeltaTime ) /* If fSoundTimePassed < 0, the sound has probably looped. */ if( sLastFile == ThisFile && fSoundTimePassed >= 0 && fabsf(fDiff) > 0.003f ) LOG->Trace("Song position skip in %s: expected %.3f, got %.3f (cur %f, prev %f) (%.3f difference)", - Basename(ThisFile).c_str(), fExpectedTimePassed, fSoundTimePassed, fSeconds, GAMESTATE->m_fMusicSeconds, fDiff ); + Basename(ThisFile).c_str(), fExpectedTimePassed, fSoundTimePassed, fSeconds, GAMESTATE->m_Position.m_fMusicSeconds, fDiff ); sLastFile = ThisFile; } @@ -599,7 +599,7 @@ void GameSoundManager::Update( float fDeltaTime ) { /* We're still waiting for the new sound to start playing, so keep using the * old timing data and fake the time. */ - GAMESTATE->UpdateSongPosition( GAMESTATE->m_fMusicSeconds + fDeltaTime, g_Playing->m_Timing ); + GAMESTATE->UpdateSongPosition( GAMESTATE->m_Position.m_fMusicSeconds + fDeltaTime, g_Playing->m_Timing ); } else { @@ -614,7 +614,7 @@ void GameSoundManager::Update( float fDeltaTime ) { static int iBeatLastCrossed = 0; - float fSongBeat = GAMESTATE->m_fSongBeat; + float fSongBeat = GAMESTATE->m_Position.m_fSongBeat; int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); iRowNow = max( 0, iRowNow ); @@ -638,7 +638,7 @@ void GameSoundManager::Update( float fDeltaTime ) NoteData &lights = g_Playing->m_Lights; if( lights.GetNumTracks() > 0 ) // lights data was loaded { - const float fSongBeat = GAMESTATE->m_fLightSongBeat; + const float fSongBeat = GAMESTATE->m_Position.m_fLightSongBeat; const int iSongRow = BeatToNoteRowNotRounded( fSongBeat ); static int iRowLastCrossed = 0; diff --git a/src/GameState.cpp b/src/GameState.cpp index 4df8259744..54330d8dfd 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -958,7 +958,7 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti int iThrowAway; timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); - Actor::SetBGMTime( m_Position.m_fMusicSecondsVisible, m_Position.m_fSongBeatVisible, fPositionSeconds, m_Position.m_fSongBeatNoOffset ); + Actor::SetBGMTime( GAMESTATE->m_fMusicSecondsVisible, GAMESTATE->m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } @@ -2252,11 +2252,11 @@ public: DEFINE_METHOD( GetHardestStepsDifficulty, GetHardestStepsDifficulty() ) DEFINE_METHOD( IsEventMode, IsEventMode() ) DEFINE_METHOD( GetNumPlayersEnabled, GetNumPlayersEnabled() ) - DEFINE_METHOD( GetSongBeat, m_fSongBeat ) + DEFINE_METHOD( GetSongBeat, m_Position.m_fSongBeat ) DEFINE_METHOD( GetSongBeatVisible, m_fSongBeatVisible ) - DEFINE_METHOD( GetSongBPS, m_fCurBPS ) - DEFINE_METHOD( GetSongFreeze, m_bFreeze ) - DEFINE_METHOD( GetSongDelay, m_bDelay ) + DEFINE_METHOD( GetSongBPS, m_Position.m_fCurBPS ) + DEFINE_METHOD( GetSongFreeze, m_Position.m_bFreeze ) + DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay ) DEFINE_METHOD( GetGameplayLeadIn, m_bGameplayLeadIn ) DEFINE_METHOD( GetCoins, m_iCoins ) DEFINE_METHOD( IsSideJoined, m_bSideIsJoined[Enum::Check(L, 1)] ) @@ -2395,7 +2395,7 @@ public: static int JoinPlayer( T* p, lua_State *L ) { p->JoinPlayer(Enum::Check(L, 1)); return 0; } static int UnjoinPlayer( T* p, lua_State *L ) { p->UnjoinPlayer(Enum::Check(L, 1)); return 0; } static int GetSongPercent( T* p, lua_State *L ) { lua_pushnumber(L, p->GetSongPercent(FArg(1))); return 1; } - DEFINE_METHOD( GetCurMusicSeconds, m_fMusicSeconds ) + DEFINE_METHOD( GetCurMusicSeconds, m_Position.m_fMusicSeconds ) DEFINE_METHOD( GetWorkoutGoalComplete, m_bWorkoutGoalComplete ) static int GetCharacter( T* p, lua_State *L ) { p->m_pCurCharacters[Enum::Check(L, 1)]->PushSelf(L); return 1; } diff --git a/src/GameplayAssist.cpp b/src/GameplayAssist.cpp index 97a324416d..ac9ae328b3 100644 --- a/src/GameplayAssist.cpp +++ b/src/GameplayAssist.cpp @@ -25,7 +25,7 @@ void GameplayAssist::PlayTicks( const NoteData &nd ) * will start coming out the speaker. Compensate for this by boosting fPositionSeconds * ahead. This is just to make sure that we request the sound early enough for it to * come out on time; the actual precise timing is handled by SetStartTime. */ - float fPositionSeconds = GAMESTATE->m_fMusicSeconds; + float fPositionSeconds = GAMESTATE->m_Position.m_fMusicSeconds; fPositionSeconds += SOUNDMAN->GetPlayLatency() + (float)CommonMetrics::TICK_EARLY_SECONDS + 0.250f; const TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; const float fSongBeat = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); @@ -47,11 +47,11 @@ void GameplayAssist::PlayTicks( const NoteData &nd ) { const float fTickBeat = NoteRowToBeat( iClapRow ); const float fTickSecond = timing.GetElapsedTimeFromBeatNoOffset( fTickBeat ); - float fSecondsUntil = fTickSecond - GAMESTATE->m_fMusicSeconds; + float fSecondsUntil = fTickSecond - GAMESTATE->m_Position.m_fMusicSeconds; fSecondsUntil /= GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; /* 2x music rate means the time until the tick is halved */ RageSoundParams p; - p.m_StartTime = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)CommonMetrics::TICK_EARLY_SECONDS); + p.m_StartTime = GAMESTATE->m_Position.m_LastBeatUpdate + (fSecondsUntil - (float)CommonMetrics::TICK_EARLY_SECONDS); m_soundAssistClap.Play( &p ); } } @@ -83,11 +83,11 @@ void GameplayAssist::PlayTicks( const NoteData &nd ) { const float fTickBeat = NoteRowToBeat( iMetronomeRow ); const float fTickSecond = timing.GetElapsedTimeFromBeatNoOffset( fTickBeat ); - float fSecondsUntil = fTickSecond - GAMESTATE->m_fMusicSeconds; + float fSecondsUntil = fTickSecond - GAMESTATE->m_Position.m_fMusicSeconds; fSecondsUntil /= GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; /* 2x music rate means the time until the tick is halved */ RageSoundParams p; - p.m_StartTime = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)CommonMetrics::TICK_EARLY_SECONDS); + p.m_StartTime = GAMESTATE->m_Position.m_LastBeatUpdate + (fSecondsUntil - (float)CommonMetrics::TICK_EARLY_SECONDS); if( bIsMeasure ) m_soundAssistMetronomeMeasure.Play( &p ); else diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index f2cba6c337..041613e914 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1347,10 +1347,10 @@ void ScreenGameplay::StartPlayingSong( float fMinTimeToNotes, float fMinTimeToMu m_pSoundMusic->Pause( true ); /* Make sure GAMESTATE->m_fMusicSeconds is set up. */ - GAMESTATE->m_fMusicSeconds = -5000; + GAMESTATE->m_Position.m_fMusicSeconds = -5000; UpdateSongPosition(0); - ASSERT( GAMESTATE->m_fMusicSeconds > -4000 ); /* make sure the "fake timer" code doesn't trigger */ + ASSERT( GAMESTATE->m_Position.m_fMusicSeconds > -4000 ); /* make sure the "fake timer" code doesn't trigger */ } @@ -1405,7 +1405,7 @@ void ScreenGameplay::PlayAnnouncer( RString type, float fSeconds ) if( m_DancingState != STATE_DANCING ) return; if( GAMESTATE->m_pCurSong == NULL || // this will be true on ScreenDemonstration sometimes - GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat ) + GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat ) return; if( m_fTimeSinceLastDancingComment < fSeconds ) @@ -1687,7 +1687,7 @@ void ScreenGameplay::Update( float fDeltaTime ) // update fGameplaySeconds STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime; - if( GAMESTATE->m_fSongBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + if( GAMESTATE->m_Position.m_fSongBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) { STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime; @@ -1707,7 +1707,7 @@ void ScreenGameplay::Update( float fDeltaTime ) if( bAllReallyFailed ) fSecondsToStartTransitioningOut += BEGIN_FAILED_DELAY; - if( GAMESTATE->m_fMusicSeconds >= fSecondsToStartTransitioningOut && !m_NextSong.IsTransitioning() ) + if( GAMESTATE->m_Position.m_fMusicSeconds >= fSecondsToStartTransitioningOut && !m_NextSong.IsTransitioning() ) this->PostScreenMessage( SM_NotesEnded, 0 ); } @@ -1843,8 +1843,8 @@ void ScreenGameplay::Update( float fDeltaTime ) float ScreenGameplay::GetHasteRate() { - if( GAMESTATE->m_fMusicSeconds < GAMESTATE->m_fLastHasteUpdateMusicSeconds || // new song - GAMESTATE->m_fMusicSeconds > GAMESTATE->m_fLastHasteUpdateMusicSeconds + 4 ) + if( GAMESTATE->m_Position.m_fMusicSeconds < GAMESTATE->m_fLastHasteUpdateMusicSeconds || // new song + GAMESTATE->m_Position.m_fMusicSeconds > GAMESTATE->m_fLastHasteUpdateMusicSeconds + 4 ) { bool bAnyPlayerHitAllNotes = false; FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi ) @@ -1865,7 +1865,7 @@ float ScreenGameplay::GetHasteRate() GAMESTATE->m_fHasteRate += 0.1f; CLAMP( GAMESTATE->m_fHasteRate, -1.0f, +1.0f ); - GAMESTATE->m_fLastHasteUpdateMusicSeconds = GAMESTATE->m_fMusicSeconds; + GAMESTATE->m_fLastHasteUpdateMusicSeconds = GAMESTATE->m_Position.m_fMusicSeconds; } /* If the life meter is less than half full, push the haste rate down to let @@ -1914,7 +1914,7 @@ void ScreenGameplay::UpdateLights() ZERO( bBlinkGameButton ); bool bCrossedABeat = false; { - const float fSongBeat = GAMESTATE->m_fLightSongBeat; + const float fSongBeat = GAMESTATE->m_Position.m_fLightSongBeat; const int iSongRow = BeatToNoteRowNotRounded( fSongBeat ); static int iRowLastCrossed = 0; @@ -1968,7 +1968,7 @@ void ScreenGameplay::UpdateLights() } // Before the first beat of the song, all cabinet lights solid on (except for menu buttons). - bool bOverrideCabinetBlink = (GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat); + bool bOverrideCabinetBlink = (GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat); FOREACH_CabinetLight( cl ) bBlinkCabinetLight[cl] |= bOverrideCabinetBlink; @@ -1994,7 +1994,7 @@ void ScreenGameplay::SendCrossedMessages() { static int iRowLastCrossed = 0; - float fPositionSeconds = GAMESTATE->m_fMusicSeconds; + float fPositionSeconds = GAMESTATE->m_Position.m_fMusicSeconds; float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ); int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); @@ -2032,7 +2032,7 @@ void ScreenGameplay::SendCrossedMessages() { float fNoteWillCrossInSeconds = MESSAGE_SPACING_SECONDS * i; - float fPositionSeconds = GAMESTATE->m_fMusicSeconds + fNoteWillCrossInSeconds; + float fPositionSeconds = GAMESTATE->m_Position.m_fMusicSeconds + fNoteWillCrossInSeconds; float fSongBeat = GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime( fPositionSeconds ); int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); diff --git a/src/ScreenHowToPlay.cpp b/src/ScreenHowToPlay.cpp index 877fb693c4..21aeef437b 100644 --- a/src/ScreenHowToPlay.cpp +++ b/src/ScreenHowToPlay.cpp @@ -209,7 +209,7 @@ void ScreenHowToPlay::Step() #define ST_JUMPUD (ST_UP | ST_DOWN) int iStep = 0; - const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat + 0.6f ); + const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat + 0.6f ); // if we want to miss from here on out, don't process steps. if( m_iW2s < m_iNumW2s && m_NoteData.IsThereATapAtRow( iNoteRow ) ) { @@ -230,10 +230,10 @@ void ScreenHowToPlay::Step() m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f ); m_pmCharacter->StopTweening(); - m_pmCharacter->BeginTweening( GAMESTATE->m_fCurBPS /8, TWEEN_LINEAR ); + m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /8, TWEEN_LINEAR ); m_pmCharacter->SetRotationY( 90 ); - m_pmCharacter->BeginTweening( (1/(GAMESTATE->m_fCurBPS * 2) ) ); //sleep between jump-frames - m_pmCharacter->BeginTweening( GAMESTATE->m_fCurBPS /6, TWEEN_LINEAR ); + m_pmCharacter->BeginTweening( (1/(GAMESTATE->m_Position.m_fCurBPS * 2) ) ); //sleep between jump-frames + m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /6, TWEEN_LINEAR ); m_pmCharacter->SetRotationY( 0 ); break; } @@ -248,7 +248,7 @@ void ScreenHowToPlay::Update( float fDelta ) m_fFakeSecondsIntoSong += fDelta; static int iLastNoteRowCounted = 0; - int iCurNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ); + int iCurNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat ); if( iCurNoteRow != iLastNoteRowCounted &&m_NoteData.IsThereATapAtRow(iCurNoteRow) ) { From a6ea7bdf501aea1438f279164a01469578d420a2 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 14:46:20 -0500 Subject: [PATCH 056/333] attempt to get rid of some madness --- src/JsonUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/JsonUtil.cpp b/src/JsonUtil.cpp index e7eb597e21..be736ea4b5 100644 --- a/src/JsonUtil.cpp +++ b/src/JsonUtil.cpp @@ -4,8 +4,8 @@ #include "RageUtil.h" #include "RageLog.h" #include "arch/Dialog/Dialog.h" -#include "../extern/jsoncpp/include/json/reader.h" -#include "../extern/jsoncpp/include/json/writer.h" +#include "json/reader.h" +#include "json/writer.h" bool JsonUtil::LoadFromString(Json::Value &root, RString sData, RString &sErrorOut) { From 61839545904f0aee5f78f52fc4d18a107b304f93 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 15:47:16 -0400 Subject: [PATCH 057/333] [splittiming] More work needed on this one. --- src/NotesLoaderKSF.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 14e6b4bca7..42abc7032c 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -41,6 +41,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount ); return false; } + out.m_Timing.AddTickcountSegment(TickcountSegment(0, iTickCount)); } else if( sValueName=="STEP" ) { @@ -133,6 +134,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, case StepsType_pump_single: notedata.SetNumTracks( 5 ); break; case StepsType_pump_couple: notedata.SetNumTracks( 10 ); break; case StepsType_pump_double: notedata.SetNumTracks( 10 ); break; + case StepsType_pump_routine: notedata.SetNumTracks( 10 ); break; // future files may have this? case StepsType_pump_halfdouble: notedata.SetNumTracks( 6 ); break; default: FAIL_M( ssprintf("%i", out.m_StepsType) ); } @@ -184,7 +186,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, }*/ if( BeginsWith(sRowString, "|B") || BeginsWith(sRowString, "|D") || BeginsWith(sRowString, "|E") ) { - // These don't have to be worried about here: the changes and stops were already added. + // TODO: Update for Split Timing. continue; } else if ( BeginsWith(sRowString, "|T") ) @@ -192,6 +194,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, RString temp = sRowString.substr(2,sRowString.size()-3); newTick = atoi(temp); bTickChangeNeeded = true; + out.m_Timing.AddTickcountSegment(TickcountSegment(fCurBeat, newTick)); continue; } else From aa58884f8f5e3255e1bfbf84b79cfeaa049f0b73 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 18:59:09 -0500 Subject: [PATCH 058/333] add NotesLoader/WriterJson --- extern/jsoncpp/include/json/value.h | 7 + src/JsonUtil.h | 186 +++++++++++++++++++++- src/NotesLoaderJson.cpp | 238 ++++++++++++++++++++++++++++ src/NotesLoaderJson.h | 41 +++++ src/NotesWriterJson.cpp | 230 +++++++++++++++++++++++++++ src/NotesWriterJson.h | 40 +++++ src/Song.h | 1 + src/StepMania-net2008.vcproj | 16 ++ 8 files changed, 757 insertions(+), 2 deletions(-) create mode 100644 src/NotesLoaderJson.cpp create mode 100644 src/NotesLoaderJson.h create mode 100644 src/NotesWriterJson.cpp create mode 100644 src/NotesWriterJson.h diff --git a/extern/jsoncpp/include/json/value.h b/extern/jsoncpp/include/json/value.h index 58bfd88e7a..0cf4ca76cf 100644 --- a/extern/jsoncpp/include/json/value.h +++ b/extern/jsoncpp/include/json/value.h @@ -234,6 +234,13 @@ namespace Json { double asDouble() const; bool asBool() const; + bool TryGet( std::string &out ) const { if(!isString()) return false; out=asString(); return true; } + bool TryGet( int &out ) const { if(!isInt()) return false; out=asInt(); return true; } + bool TryGet( UInt &out ) const { if(!isUInt()) return false; out=asUInt(); return true; } + bool TryGet( double &out ) const { if(!isDouble()) return false; out=asDouble(); return true; } + bool TryGet( float &out ) const { if(!isDouble()) return false; out=(float)asDouble(); return true; } + bool TryGet( bool &out ) const { if(!isBool()) return false; out=asBool(); return true; } + bool isNull() const; bool isBool() const; bool isInt() const; diff --git a/src/JsonUtil.h b/src/JsonUtil.h index 8c17bb1af2..97136a4f14 100644 --- a/src/JsonUtil.h +++ b/src/JsonUtil.h @@ -1,9 +1,10 @@ +/** @brief Utilities for handling JSON data. */ #ifndef JsonUtil_H #define JsonUtil_H class RageFileBasic; -#include "../extern/jsoncpp/include/json/value.h" -/** @brief Utilities for handling JSON data. */ +#include "json/value.h" + namespace JsonUtil { bool LoadFromString( Json::Value &root, RString sData, RString &sErrorOut ); @@ -31,6 +32,86 @@ namespace JsonUtil fn(*v[i], root[i]); } + template + static void SerializeArray(const V &v, void fn(const T &, Json::Value &), Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + fn( *iter, root[i++] ); + } + + template + static void SerializeArrayValues(const V &v, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + root[i++] = *iter; + } + + template + static void SerializeArrayObjects(const V &v, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + iter->Serialize( root[i++] ); + } + + template + static void SerializeStringToObjectMap(const M &m, F fnEnumToString(E e), Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + iter->second.Serialize( root[ fnEnumToString(iter->first) ] ); + } + + template + static void SerializeStringToValueMap(const M &m, F fnToString(E e), Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + root[ fnToString(iter->first) ] = iter->second; + } + + template + static void SerializeValueToValueMap(const M &m, Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + root[ (iter->first) ] = iter->second; + } + + // Serialize a map that has a non-string key type + template + static void SerializeObjectToObjectMapAsArray(const V &v, const RString &sKeyName, const RString &sValueName, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + { + Json::Value &v = root[i++]; + iter->first.Serialize( v[sKeyName] ); + iter->second.Serialize( v[sValueName] ); + } + } + + template + static void SerializeObjectToValueMapAsArray(const V &v, const RString &sKeyName, const RString &sValueName, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + { + Json::Value &v = root[i++]; + iter->first.Serialize( v[sKeyName] ); + v[sValueName] = iter->second; + } + } + template static void SerializeVectorValues(const vector &v, Json::Value &root) { @@ -48,6 +129,14 @@ namespace JsonUtil fn(v[i], root[i]); } + template + static void DeserializeArrayObjects( V &v, const Json::Value &root) + { + v.resize( root.size() ); + for( unsigned i=0; i static void DeserializeVectorPointers(vector &v, void fn(T &, const Json::Value &), const Json::Value &root) { @@ -61,6 +150,99 @@ namespace JsonUtil } } + template + static void DeserializeArrayValues(vector &v, const Json::Value &root) + { + v.clear(); + for( unsigned i=0; i + static void DeserializeArrayValuesIntoSet(S &s, const Json::Value &root) + { + s.clear(); + for( unsigned i=0; i + static void DeserializeArrayValuesIntoVector(vector &v, const Json::Value &root) + { + v.clear(); + for( unsigned i=0; i + static void DeserializeValueToValueMap(M &m, const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + (*iter).TryGet( m[ iter.memberName() ] ); + } + + template + static void DeserializeStringToValueMap(M &m, F fnToValue(E e), const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + (*iter).TryGet( m[ fnToValue(iter.memberName()) ] ); + } + + template + static void DeserializeStringToObjectMap(M &m, F fnToValue(E e), const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + m[ fnToValue(iter.memberName()) ].Deserialize( *iter ); + } + + // Serialize a map that has a non-string key type + template + static void DeserializeObjectToObjectMapAsArray(map &m, const RString &sKeyName, const RString &sValueName, const Json::Value &root) + { + m.clear(); + ASSERT( root.type() == Json::arrayValue ); + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + { + ASSERT( (*iter).type() == Json::objectValue ); + K k; + if( !k.Deserialize( (*iter)[sKeyName] ) ) + continue; + V v; + if( !v.Deserialize( (*iter)[sValueName] ) ) + continue; + m[k] = v; + } + } + + template + static void DeserializeObjectToValueMapAsArray(map &m, const RString &sKeyName, const RString &sValueName, const Json::Value &root) + { + for( unsigned i=0; i static void DeserializeVectorValues(vector &v, const Json::Value &root) { diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp new file mode 100644 index 0000000000..ba7e6647f1 --- /dev/null +++ b/src/NotesLoaderJson.cpp @@ -0,0 +1,238 @@ +#include "global.h" +#include "NotesLoaderJson.h" +#include "Json/Value.h" +#include "TimingData.h" +#include "RageUtil.h" +#include "JsonUtil.h" +#include "BackgroundUtil.h" +#include "NoteData.h" +#include "Song.h" +#include "Steps.h" +#include "GameManager.h" + +void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector &out ) +{ + GetDirListing( sPath + RString("*.json"), out ); +} + +void Deserialize(BPMSegment &seg, const Json::Value &root) +{ + seg.m_iStartRow = BeatToNoteRow((float)root["Beat"].asDouble()); + seg.m_fBPS = (float)(root["BPM"].asDouble() / 60); +} + +static void Deserialize(StopSegment &seg, const Json::Value &root) +{ + seg.m_iStartRow = BeatToNoteRow((float)(root["Beat"].asDouble())); + seg.m_fStopSeconds = (float)root["Seconds"].asDouble(); +} + +static void Deserialize(TimingData &td, const Json::Value &root) +{ + JsonUtil::DeserializeVectorObjects( td.m_BPMSegments, Deserialize, root["BpmSegments"] ); + JsonUtil::DeserializeVectorObjects( td.m_StopSegments, Deserialize, root["StopSegments"] ); +} + +static void Deserialize(LyricSegment &o, const Json::Value &root) +{ + o.m_fStartTime = (float)root["StartTime"].asDouble(); + o.m_sLyric = root["Lyric"].asString(); + o.m_Color.FromString( root["Color"].asString() ); +} + +static void Deserialize(BackgroundDef &o, const Json::Value &root) +{ + o.m_sEffect = root["Effect"].asString(); + o.m_sFile1 = root["File1"].asString(); + o.m_sFile2 = root["File2"].asString(); + o.m_sColor1 = root["Color1"].asString(); +} + +static void Deserialize(BackgroundChange &o, const Json::Value &root ) +{ + Deserialize( o.m_def, root["Def"] ); + o.m_fStartBeat = (float)root["StartBeat"].asDouble(); + o.m_fRate = (float)root["Rate"].asDouble(); + o.m_sTransition = root["Transition"].asString(); +} + +static void Deserialize( TapNote &o, const Json::Value &root ) +{ + //if( o.type != TapNote::tap ) + if( root.isInt() ) + o.type = (TapNote::Type)root["Type"].asInt(); + //if( o.type == TapNote::hold_head ) + o.subType = (TapNote::SubType)root["SubType"].asInt(); + //root["Source"] = (int)source; + //if( !o.sAttackModifiers.empty() ) + o.sAttackModifiers = root["AttackModifiers"].asString(); + //if( o.fAttackDurationSeconds > 0 ) + o.fAttackDurationSeconds = (float)root["AttackDurationSeconds"].asDouble(); + //if( o.bKeysound ) + o.iKeysoundIndex = root["KeysoundIndex"].asInt(); + //if( o.iDuration > 0 ) + o.iDuration = root["Duration"].asInt(); + //if( o.pn != PLAYER_INVALID ) + o.pn = (PlayerNumber)root["PlayerNumber"].asInt(); +} + +static void Deserialize( StepsType st, NoteData &nd, const Json::Value &root ) +{ + int iTracks = nd.GetNumTracks(); + nd.SetNumTracks( iTracks ); + for( unsigned i=0; iStringToStepsType(root["StepsType"].asString()); + + o.Decompress(); + + NoteData nd; + Deserialize( o.m_StepsType, nd, root["NoteData"] ); + o.SetNoteData( nd ); + //o.SetHash( root["Hash"].asInt() ); + o.SetDescription( root["Description"].asString() ); + o.SetDifficulty( StringToDifficulty(root["Difficulty"].asString()) ); + o.SetMeter( root["Meter"].asInt() ); + + RadarValues rv[NUM_PLAYERS]; + FOREACH_PlayerNumber( pn ) + { + Deserialize( rv[pn], root["RadarValues"] ); + } + o.SetCachedRadarValues( rv ); +} + +static void Deserialize( Song &out, const Json::Value &root ) +{ + out.SetSongDir( root["SongDir"].asString() ); + out.m_sGroupName = root["GroupName"].asString(); + out.m_sMainTitle = root["Title"].asString(); + out.m_sSubTitle = root["SubTitle"].asString(); + out.m_sArtist = root["Artist"].asString(); + out.m_sMainTitleTranslit = root["TitleTranslit"].asString(); + out.m_sSubTitleTranslit = root["SubTitleTranslit"].asString(); + out.m_sGenre = root["Genre"].asString(); + out.m_sCredit = root["Credit"].asString(); + out.m_sBannerFile = root["Banner"].asString(); + out.m_sBackgroundFile = root["Background"].asString(); + out.m_sLyricsFile = root["LyricsFile"].asString(); + out.m_sCDTitleFile = root["CDTitle"].asString(); + out.m_sMusicFile = root["Music"].asString(); + out.m_Timing.m_fBeat0OffsetInSeconds = (float)root["Offset"].asDouble(); + out.m_fMusicSampleStartSeconds = (float)root["SampleStart"].asDouble(); + out.m_fMusicSampleLengthSeconds = (float)root["SampleLength"].asDouble(); + RString sSelectable = root["Selectable"].asString(); + if( !stricmp(sSelectable,"YES") ) + out.m_SelectionDisplay = out.SHOW_ALWAYS; + else if(!stricmp(sSelectable,"NO")) + out.m_SelectionDisplay = out.SHOW_NEVER; + + out.m_fFirstBeat = (float)root["FirstBeat"].asDouble(); + out.m_fLastBeat = (float)root["LastBeat"].asDouble(); + out.m_sSongFileName = root["SongFileName"].asString(); + out.m_bHasMusic = root["HasMusic"].asBool(); + out.m_bHasBanner = root["HasBanner"].asBool(); + out.m_fMusicLengthSeconds = (float)root["MusicLengthSeconds"].asDouble(); + + RString sDisplayBPMType = root["DisplayBpmType"].asString(); + if( sDisplayBPMType == "*" ) + out.m_DisplayBPMType = DISPLAY_BPM_RANDOM; + else + out.m_DisplayBPMType = DISPLAY_BPM_SPECIFIED; + + if( out.m_DisplayBPMType == DISPLAY_BPM_SPECIFIED ) + { + out.m_fSpecifiedBPMMin = (float)root["SpecifiedBpmMin"].asDouble(); + out.m_fSpecifiedBPMMax = (float)root["SpecifiedBpmMax"].asDouble(); + } + + Deserialize( out.m_Timing, root["TimingData"] ); + JsonUtil::DeserializeVectorObjects( out.m_LyricSegments, Deserialize, root["LyricSegments"] ); + + { + const Json::Value &root2 = root["BackgroundChanges"]; + FOREACH_BackgroundLayer( bl ) + { + const Json::Value &root3 = root2[bl]; + vector &vBgc = out.GetBackgroundChanges(bl); + JsonUtil::DeserializeVectorObjects( vBgc, Deserialize, root3 ); + } + } + + { + vector &vBgc = out.GetForegroundChanges(); + JsonUtil::DeserializeVectorObjects( vBgc, Deserialize, root["ForegroundChanges"] ); + } + + JsonUtil::DeserializeArrayValuesIntoVector( out.m_vsKeysoundFile, root["KeySounds"] ); + + { + vector vpSteps; + JsonUtil::DeserializeVectorPointers( vpSteps, Deserialize, root["Charts"] ); + FOREACH( Steps*, vpSteps, iter ) + out.AddSteps( *iter ); + } + +} + +bool NotesLoaderJson::LoadFromJsonFile( const RString &sPath, Song &out ) +{ + Json::Value root; + if( !JsonUtil::LoadFromFileShowErrors(root,sPath) ) + return false; + + Deserialize(out, root); + + return true; +} + +bool NotesLoaderJson::LoadFromDir( const RString &sPath, Song &out ) +{ + return LoadFromJsonFile(sPath, out); +} + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/NotesLoaderJson.h b/src/NotesLoaderJson.h new file mode 100644 index 0000000000..c96629ffd8 --- /dev/null +++ b/src/NotesLoaderJson.h @@ -0,0 +1,41 @@ +/* JsonLoader - Reads a Song from a .json file. */ + +#ifndef NotesLoaderJson_H +#define NotesLoaderJson_H + +#include "NotesLoader.h" +class Song; + +namespace NotesLoaderJson +{ + void GetApplicableFiles( const RString &sPath, vector &out ); + bool LoadFromDir( const RString &sPath, Song &out ); + bool LoadFromJsonFile( const RString &sPath, Song &out ); +}; + +#endif + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp new file mode 100644 index 0000000000..984e4f92da --- /dev/null +++ b/src/NotesWriterJson.cpp @@ -0,0 +1,230 @@ +#include "global.h" +#include "NotesWriterJson.h" +#include "TimingData.h" +#include "Json/Value.h" +#include "JsonUtil.h" +#include "Song.h" +#include "BackgroundUtil.h" +#include "Steps.h" +#include "NoteData.h" +#include "GameManager.h" + +void Serialize(const BPMSegment &seg, Json::Value &root) +{ + root["Beat"] = NoteRowToBeat(seg.m_iStartRow); + root["BPM"] = seg.m_fBPS * 60; +} + +static void Serialize(const StopSegment &seg, Json::Value &root) +{ + root["Beat"] = NoteRowToBeat(seg.m_iStartRow); + root["Seconds"] = seg.m_fStopSeconds; +} + +static void Serialize(const TimingData &td, Json::Value &root) +{ + JsonUtil::SerializeVectorObjects( td.m_BPMSegments, Serialize, root["BpmSegments"] ); + JsonUtil::SerializeVectorObjects( td.m_StopSegments, Serialize, root["StopSegments"] ); +} + +static void Serialize(const LyricSegment &o, Json::Value &root) +{ + root["StartTime"] = (float)o.m_fStartTime; + root["Lyric"] = o.m_sLyric; + root["Color"] = o.m_Color.ToString(); +} + +static void Serialize(const BackgroundDef &o, Json::Value &root) +{ + root["Effect"] = o.m_sEffect; + root["File1"] = o.m_sFile1; + root["File2"] = o.m_sFile2; + root["Color1"] = o.m_sColor1; +} + +static void Serialize(const BackgroundChange &o, Json::Value &root ) +{ + Serialize( o.m_def, root["Def"] ); + root["StartBeat"] = o.m_fStartBeat; + root["Rate"] = o.m_fRate; + root["Transition"] = o.m_sTransition; +} + +static void Serialize( const TapNote &o, Json::Value &root ) +{ + root = Json::Value(Json::objectValue); + + if( o.type != TapNote::tap ) + root["Type"] = (int)o.type; + if( o.type == TapNote::hold_head ) + root["SubType"] = (int)o.subType; + //root["Source"] = (int)source; + if( !o.sAttackModifiers.empty() ) + root["AttackModifiers"] = o.sAttackModifiers; + if( o.fAttackDurationSeconds > 0 ) + root["AttackDurationSeconds"] = o.fAttackDurationSeconds; + if( o.iKeysoundIndex != -1 ) + root["KeysoundIndex"] = o.iKeysoundIndex; + if( o.iDuration > 0 ) + root["Duration"] = o.iDuration; + if( o.pn != PLAYER_INVALID ) + root["PlayerNumber"] = (int)o.pn; +} + +static void Serialize( const NoteData &o, Json::Value &root ) +{ + root = Json::Value(Json::arrayValue); + int iNumTracks = o.GetNumTracks(); + for(int t=0; tfirst; + TapNote tn = begin->second; + root.resize( root.size()+1 ); + Json::Value &root2 = root[ root.size()-1 ]; + root2 = Json::Value(Json::arrayValue); + root2.resize(3); + root2[(unsigned)0] = NoteRowToBeat(iRow); + root2[1] = t; + Serialize( tn, root2[2] ); + } + } +} + +static void Serialize( const RadarValues &o, Json::Value &root ) +{ + FOREACH_ENUM( RadarCategory, rc ) + { + root[ RadarCategoryToString(rc) ] = o.m_Values.f[rc]; + } +} + +static void Serialize( const Steps &o, Json::Value &root ) +{ + root["StepsType"] = StringConversion::ToString(o.m_StepsType); + + o.Decompress(); + + NoteData nd; + o.GetNoteData( nd ); + Serialize( nd, root["NoteData"] ); + root["Hash"] = o.GetHash(); + root["Description"] = o.GetDescription(); + root["Difficulty"] = DifficultyToString(o.GetDifficulty()); + root["Meter"] = o.GetMeter(); + Serialize( o.GetRadarValues( PLAYER_1 ), root["RadarValues"] ); +} + + +bool NotesWriterJson::WriteSong( const RString &sFile, const Song &out, bool bWriteSteps ) +{ + Json::Value root; + root["SongDir"] = out.GetSongDir(); + root["GroupName"] = out.m_sGroupName; + root["Title"] = out.m_sMainTitle; + root["SubTitle"] = out.m_sSubTitle; + root["Artist"] = out.m_sArtist; + root["TitleTranslit"] = out.m_sMainTitleTranslit; + root["SubTitleTranslit"] = out.m_sSubTitleTranslit; + root["Genre"] = out.m_sGenre; + root["Credit"] = out.m_sCredit; + root["Banner"] = out.m_sBannerFile; + root["Background"] = out.m_sBackgroundFile; + root["LyricsFile"] = out.m_sLyricsFile; + root["CDTitle"] = out.m_sCDTitleFile; + root["Music"] = out.m_sMusicFile; + root["Offset"] = out.m_Timing.m_fBeat0OffsetInSeconds; + root["SampleStart"] = out.m_fMusicSampleStartSeconds; + root["SampleLength"] = out.m_fMusicSampleLengthSeconds; + if( out.m_SelectionDisplay == Song::SHOW_ALWAYS ) + root["Selectable"] = "YES"; + else if( out.m_SelectionDisplay == Song::SHOW_NEVER ) + root["Selectable"] = "NO"; + else + root["Selectable"] = "YES"; + + root["FirstBeat"] = out.m_fFirstBeat; + root["LastBeat"] = out.m_fLastBeat; + root["SongFileName"] = out.m_sSongFileName; + root["HasMusic"] = out.m_bHasMusic; + root["HasBanner"] = out.m_bHasBanner; + root["MusicLengthSeconds"] = out.m_fMusicLengthSeconds; + + root["DisplayBpmType"] = StringConversion::ToString(out.m_DisplayBPMType); + if( out.m_DisplayBPMType == DISPLAY_BPM_SPECIFIED ) + { + root["SpecifiedBpmMin"] = out.m_fSpecifiedBPMMin; + root["SpecifiedBpmMax"] = out.m_fSpecifiedBPMMax; + } + + Serialize( out.m_Timing, root["TimingData"] ); + JsonUtil::SerializeVectorObjects( out.m_LyricSegments, Serialize, root["LyricSegments"] ); + + { + Json::Value &root2 = root["BackgroundChanges"]; + FOREACH_BackgroundLayer( bl ) + { + Json::Value &root3 = root2[bl]; + const vector &vBgc = out.GetBackgroundChanges(bl); + JsonUtil::SerializeVectorObjects( vBgc, Serialize, root3 ); + } + } + + { + const vector &vBgc = out.GetForegroundChanges(); + JsonUtil::SerializeVectorObjects( vBgc, Serialize, root["ForegroundChanges"] ); + } + + JsonUtil::SerializeArrayValues( out.m_vsKeysoundFile, root["KeySounds"] ); + + if( bWriteSteps ) + { + vector vpSteps; + FOREACH_CONST( Steps*, out.GetAllSteps(), iter ) + { + if( (*iter)->IsAutogen() ) + continue; + vpSteps.push_back( *iter ); + } + JsonUtil::SerializeVectorPointers( vpSteps, Serialize, root["Charts"] ); + } + + return JsonUtil::WriteFile( root, sFile, false ); +} + +bool NotesWriterJson::WriteSteps( const RString &sFile, const Steps &out ) +{ + Json::Value root; + Serialize( out, root ); + return JsonUtil::WriteFile( root, sFile, false ); +} + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/NotesWriterJson.h b/src/NotesWriterJson.h new file mode 100644 index 0000000000..c873733f96 --- /dev/null +++ b/src/NotesWriterJson.h @@ -0,0 +1,40 @@ +/* NotesWriterJson - Writes a Song to a .json file. */ + +#ifndef NotesWriterJson_H +#define NotesWriterJson_H + +class Song; +class Steps; + +namespace NotesWriterJson +{ + static bool WriteSong( const RString &sFile, const Song &out, bool bWriteSteps ); + static bool WriteSteps( const RString &sFile, const Steps &out ); +}; + +#endif + +/* + * (c) 2001-2010 Chris Danford, Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/Song.h b/src/Song.h index 9c105a5732..479457ec56 100644 --- a/src/Song.h +++ b/src/Song.h @@ -73,6 +73,7 @@ class Song RString m_sSongDir; public: void SetSongDir( const RString sDir ) { m_sSongDir = sDir; } + RString GetSongDir() { return m_sSongDir; } /** @brief When should this song be displayed in the music wheel? */ enum SelectionDisplay diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index 7d7f87a40d..2dfb5b7eb1 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -1575,6 +1575,14 @@ RelativePath="NotesLoaderDWI.h" > + + + + @@ -1755,6 +1763,14 @@ RelativePath="NotesWriterDWI.h" > + + + + From 5e262bec0fe694e6b878cf71aab4145965c918b0 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 19:03:30 -0500 Subject: [PATCH 059/333] add NotesLoader/WriterJson to makefile.am --- src/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 6a50b53cf8..044b03e9bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -158,10 +158,12 @@ ModsGroup.cpp ModsGroup.h \ NoteData.cpp NoteData.h NoteDataUtil.cpp NoteDataUtil.h NoteDataWithScoring.cpp NoteDataWithScoring.h \ NoteTypes.cpp NoteTypes.h NotesLoader.cpp NotesLoader.h \ NotesLoaderBMS.cpp NotesLoaderBMS.h NotesLoaderDWI.cpp NotesLoaderDWI.h \ +NotesLoaderJson.cpp NotesLoaderJson.h \ NotesLoaderKSF.cpp NotesLoaderKSF.h NotesLoaderMidi.cpp NotesLoaderMidi.h \ NotesLoaderPMS.cpp NotesLoaderPMS.h NotesLoaderSM.cpp NotesLoaderSM.h \ NotesLoaderSSC.cpp NotesLoaderSSC.h NotesLoaderSMA.cpp NotesLoaderSMA.h \ NotesWriterDWI.cpp NotesWriterDWI.h \ +NotesWriterJson.cpp NotesWriterJson.h \ NotesWriterSM.cpp NotesWriterSM.h NotesWriterSSC.cpp NotesWriterSSC.h \ OptionRowHandler.cpp OptionRowHandler.h OptionsList.cpp OptionsList.h \ PlayerAI.cpp PlayerAI.h PlayerNumber.cpp PlayerNumber.h PlayerOptions.cpp PlayerOptions.h \ From f1546b4283960a204ad4263893bd8d8f01d3594f Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 19:43:30 -0500 Subject: [PATCH 060/333] change to GetTapNoteRange and use MAX_NOTE_ROW --- src/NotesWriterJson.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index 984e4f92da..43f7ab5bc9 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -78,7 +78,7 @@ static void Serialize( const NoteData &o, Json::Value &root ) for(int t=0; t Date: Tue, 10 May 2011 19:46:08 -0500 Subject: [PATCH 061/333] attempt a fix for mac compiling --- src/NotesWriterJson.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index 43f7ab5bc9..cc91114bc9 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -74,8 +74,7 @@ static void Serialize( const TapNote &o, Json::Value &root ) static void Serialize( const NoteData &o, Json::Value &root ) { root = Json::Value(Json::arrayValue); - int iNumTracks = o.GetNumTracks(); - for(int t=0; tfirst; - TapNote tn = begin->second; + const TapNote tn = begin->second; root.resize( root.size()+1 ); Json::Value &root2 = root[ root.size()-1 ]; root2 = Json::Value(Json::arrayValue); From 8862d799fd76d5fd2e35258577f85843d7442a30 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 20:50:05 -0400 Subject: [PATCH 062/333] Add Notes*Json.* for Mac side. --- Xcode/stepmania.xcodeproj/project.pbxproj | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index a70652bcd4..88bab07032 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -27,6 +27,10 @@ 2B30D6831315EA7E00044B68 /* MouseDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B30D6811315EA7E00044B68 /* MouseDevice.h */; }; 2B76698B132FF71500586512 /* NotesLoaderSMA.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B766989132FF71500586512 /* NotesLoaderSMA.h */; }; 2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */; }; + 2B9C2E8D137A138B004C92F3 /* NotesLoaderJson.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */; }; + 2B9C2E8E137A138B004C92F3 /* NotesLoaderJson.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B9C2E8A137A138B004C92F3 /* NotesLoaderJson.h */; }; + 2B9C2E8F137A138B004C92F3 /* NotesWriterJson.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B9C2E8B137A138B004C92F3 /* NotesWriterJson.cpp */; }; + 2B9C2E90137A138B004C92F3 /* NotesWriterJson.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B9C2E8C137A138B004C92F3 /* NotesWriterJson.h */; }; 2BA7925E1304F20D002BD8E1 /* NotesLoaderSSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */; }; 2BA7925F1304F20D002BD8E1 /* NotesLoaderSSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */; }; 2BA792601304F20D002BD8E1 /* NotesWriterSSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */; }; @@ -1798,6 +1802,10 @@ 2B30D6811315EA7E00044B68 /* MouseDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MouseDevice.h; sourceTree = ""; }; 2B766989132FF71500586512 /* NotesLoaderSMA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSMA.h; path = ../src/NotesLoaderSMA.h; sourceTree = SOURCE_ROOT; }; 2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderSMA.cpp; path = ../src/NotesLoaderSMA.cpp; sourceTree = SOURCE_ROOT; }; + 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderJson.cpp; path = ../src/NotesLoaderJson.cpp; sourceTree = SOURCE_ROOT; }; + 2B9C2E8A137A138B004C92F3 /* NotesLoaderJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderJson.h; path = ../src/NotesLoaderJson.h; sourceTree = SOURCE_ROOT; }; + 2B9C2E8B137A138B004C92F3 /* NotesWriterJson.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesWriterJson.cpp; path = ../src/NotesWriterJson.cpp; sourceTree = SOURCE_ROOT; }; + 2B9C2E8C137A138B004C92F3 /* NotesWriterJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesWriterJson.h; path = ../src/NotesWriterJson.h; sourceTree = SOURCE_ROOT; }; 2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderSSC.cpp; path = ../src/NotesLoaderSSC.cpp; sourceTree = SOURCE_ROOT; }; 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSSC.h; path = ../src/NotesLoaderSSC.h; sourceTree = SOURCE_ROOT; }; 2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesWriterSSC.cpp; path = ../src/NotesWriterSSC.cpp; sourceTree = SOURCE_ROOT; }; @@ -3241,6 +3249,10 @@ 2B766980132FF62B00586512 /* NoteParsing */ = { isa = PBXGroup; children = ( + 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */, + 2B9C2E8A137A138B004C92F3 /* NotesLoaderJson.h */, + 2B9C2E8B137A138B004C92F3 /* NotesWriterJson.cpp */, + 2B9C2E8C137A138B004C92F3 /* NotesWriterJson.h */, AA6EFDED04770C79005F316C /* NotesLoader.cpp */, AA6EFDEE04770C79005F316C /* NotesLoader.h */, AA6EFDEF04770C79005F316C /* NotesLoaderBMS.cpp */, @@ -5042,6 +5054,8 @@ 2BC6132D13773C8E00CC8BBD /* pngpriv.h in Headers */, 2BC6133313773C8E00CC8BBD /* pngstruct.h in Headers */, 2BC6133E13773D2C00CC8BBD /* pnglibconf.h in Headers */, + 2B9C2E8E137A138B004C92F3 /* NotesLoaderJson.h in Headers */, + 2B9C2E90137A138B004C92F3 /* NotesWriterJson.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6301,6 +6315,8 @@ 2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */, 2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */, 2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */, + 2B9C2E8D137A138B004C92F3 /* NotesLoaderJson.cpp in Sources */, + 2B9C2E8F137A138B004C92F3 /* NotesWriterJson.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 9da3681595ac497760fee63de89b714a0311ef6a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 20:50:30 -0400 Subject: [PATCH 063/333] Revert, force const casting. Perhaps we should use these stricter casts more often. --- src/NotesWriterJson.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index cc91114bc9..e1535841e6 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -74,16 +74,17 @@ static void Serialize( const TapNote &o, Json::Value &root ) static void Serialize( const NoteData &o, Json::Value &root ) { root = Json::Value(Json::arrayValue); - for(int t=0; t < o.GetNumTracks(); t++ ) + int iNumTracks = o.GetNumTracks(); + for(int t=0; t(o).GetTapNoteRange( t, 0, MAX_NOTE_ROW, begin, end ); //NoteData::TrackMap tm = o.GetTrack(t); //FOREACHM_CONST( int, TapNote, tm, iter ) for( ; begin != end; ++begin ) { int iRow = begin->first; - const TapNote tn = begin->second; + TapNote tn = begin->second; root.resize( root.size()+1 ); Json::Value &root2 = root[ root.size()-1 ]; root2 = Json::Value(Json::arrayValue); From c19ef49bd548e6decf0454b4d5819a0a7c08f393 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 20:51:21 -0400 Subject: [PATCH 064/333] Json shadows are gone. --- src/JsonUtil.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/JsonUtil.h b/src/JsonUtil.h index 97136a4f14..87942336e0 100644 --- a/src/JsonUtil.h +++ b/src/JsonUtil.h @@ -92,9 +92,9 @@ namespace JsonUtil int i=0; for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) { - Json::Value &v = root[i++]; - iter->first.Serialize( v[sKeyName] ); - iter->second.Serialize( v[sValueName] ); + Json::Value &vv = root[i++]; + iter->first.Serialize( vv[sKeyName] ); + iter->second.Serialize( vv[sValueName] ); } } @@ -106,9 +106,9 @@ namespace JsonUtil int i=0; for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) { - Json::Value &v = root[i++]; - iter->first.Serialize( v[sKeyName] ); - v[sValueName] = iter->second; + Json::Value &vv = root[i++]; + iter->first.Serialize( vv[sKeyName] ); + vv[sValueName] = iter->second; } } From 12daa21a0ac802b3662eec11152e2a75829e7928 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Tue, 10 May 2011 19:57:58 -0500 Subject: [PATCH 065/333] ping pong, will this work? --- src/NotesWriterJson.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index e1535841e6..9dfc1d74a8 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -74,11 +74,10 @@ static void Serialize( const TapNote &o, Json::Value &root ) static void Serialize( const NoteData &o, Json::Value &root ) { root = Json::Value(Json::arrayValue); - int iNumTracks = o.GetNumTracks(); - for(int t=0; t(o).GetTapNoteRange( t, 0, MAX_NOTE_ROW, begin, end ); + NoteData::TrackMap::const_iterator begin, end; + o.GetTapNoteRange( t, 0, MAX_NOTE_ROW, begin, end ); //NoteData::TrackMap tm = o.GetTrack(t); //FOREACHM_CONST( int, TapNote, tm, iter ) for( ; begin != end; ++begin ) From 754ce93b09404189815eda4e683dd90dc257b38d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 10 May 2011 21:17:25 -0400 Subject: [PATCH 066/333] Better ordering, don't have closed branch up top. --- Xcode/stepmania.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 88bab07032..de7e2b7695 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -3249,16 +3249,14 @@ 2B766980132FF62B00586512 /* NoteParsing */ = { isa = PBXGroup; children = ( - 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */, - 2B9C2E8A137A138B004C92F3 /* NotesLoaderJson.h */, - 2B9C2E8B137A138B004C92F3 /* NotesWriterJson.cpp */, - 2B9C2E8C137A138B004C92F3 /* NotesWriterJson.h */, AA6EFDED04770C79005F316C /* NotesLoader.cpp */, AA6EFDEE04770C79005F316C /* NotesLoader.h */, AA6EFDEF04770C79005F316C /* NotesLoaderBMS.cpp */, AA6EFDF004770C79005F316C /* NotesLoaderBMS.h */, AA6EFDF104770C79005F316C /* NotesLoaderDWI.cpp */, AA6EFDF204770C79005F316C /* NotesLoaderDWI.h */, + 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */, + 2B9C2E8A137A138B004C92F3 /* NotesLoaderJson.h */, AA6EFDF304770C79005F316C /* NotesLoaderKSF.cpp */, AA6EFDF404770C79005F316C /* NotesLoaderKSF.h */, 3688B8510BD42DAA004186AD /* NotesLoaderMidi.cpp */, @@ -3271,6 +3269,8 @@ 2B766989132FF71500586512 /* NotesLoaderSMA.h */, 2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */, 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */, + 2B9C2E8B137A138B004C92F3 /* NotesWriterJson.cpp */, + 2B9C2E8C137A138B004C92F3 /* NotesWriterJson.h */, AA6EFDF704770C79005F316C /* NotesWriterDWI.cpp */, AA6EFDF804770C79005F316C /* NotesWriterDWI.h */, AA6EFDF904770C79005F316C /* NotesWriterSM.cpp */, From 88640657cc79988ea26f5e72f414080e8932e6b2 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Wed, 11 May 2011 00:46:42 -0500 Subject: [PATCH 067/333] tiny cleanup --- src/EditMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditMenu.cpp b/src/EditMenu.cpp index b595a343f6..d1fbb3db14 100644 --- a/src/EditMenu.cpp +++ b/src/EditMenu.cpp @@ -386,7 +386,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) dcOld = GetSelectedDifficulty(); m_vpSteps.clear(); - + FOREACH_ENUM( Difficulty, dc ) { if( dc == Difficulty_Edit ) From f31982985c438a5acb9b76d66cf93d432d033913 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Wed, 11 May 2011 02:01:42 -0500 Subject: [PATCH 068/333] [GameSoundManager] Added PlayAnnouncer Lua binding. --- Docs/Changelog_sm5.txt | 4 ++++ src/GameSoundManager.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index d6320fef24..27911b57bd 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,10 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/11 +---------- +* [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] + 2011/05/10 ---------- * [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] diff --git a/src/GameSoundManager.cpp b/src/GameSoundManager.cpp index 5b3ba858de..98ab3cc26c 100644 --- a/src/GameSoundManager.cpp +++ b/src/GameSoundManager.cpp @@ -806,12 +806,14 @@ public: return 0; } static int PlayOnce( T* p, lua_State *L ) { RString sPath = SArg(1); p->PlayOnce( sPath ); return 0; } + static int PlayAnnouncer( T* p, lua_State *L ) { RString sPath = SArg(1); p->PlayOnceFromAnnouncer( sPath ); return 0; } static int GetPlayerBalance( T* p, lua_State *L ) { PlayerNumber pn = Enum::Check(L, 1); lua_pushnumber( L, p->GetPlayerBalance(pn) ); return 1; } LunaGameSoundManager() { ADD_METHOD( DimMusic ); ADD_METHOD( PlayOnce ); + ADD_METHOD( PlayAnnouncer ); ADD_METHOD( GetPlayerBalance ); } }; From 292c8ece496434f98dee0240434aff7e50ed2a76 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Wed, 11 May 2011 02:12:34 -0500 Subject: [PATCH 069/333] [AnnouncerManager] Add support for "gameplay combo #" for announcer. --- Docs/Changelog_sm5.txt | 1 + src/AnnouncerManager.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 27911b57bd..cba431e5b8 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -11,6 +11,7 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/11 ---------- * [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] +* [AnnouncerManager] Add support for "gameplay combo #" for announcer. [AJ] 2011/05/10 ---------- diff --git a/src/AnnouncerManager.cpp b/src/AnnouncerManager.cpp index f64fcd624f..ee20dc427e 100644 --- a/src/AnnouncerManager.cpp +++ b/src/AnnouncerManager.cpp @@ -88,6 +88,18 @@ static const char *aliases[][2] = { { "ScreenSelectStyle comment solo", "select style comment solo" }, { "ScreenSelectStyle comment versus", "select style comment versus" }, + /* Combo compatibility: */ + { "gameplay combo 100", "gameplay 100 combo" }, + { "gameplay combo 200", "gameplay 200 combo" }, + { "gameplay combo 300", "gameplay 300 combo" }, + { "gameplay combo 400", "gameplay 400 combo" }, + { "gameplay combo 500", "gameplay 500 combo" }, + { "gameplay combo 600", "gameplay 600 combo" }, + { "gameplay combo 700", "gameplay 700 combo" }, + { "gameplay combo 800", "gameplay 800 combo" }, + { "gameplay combo 900", "gameplay 900 combo" }, + { "gameplay combo 1000", "gameplay 1000 combo" }, + { NULL, NULL } }; From d2b7c26209aa17a90ad377d075067c93d813af9d Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Wed, 11 May 2011 02:24:04 -0500 Subject: [PATCH 070/333] small cleanup + comment --- src/ThemeMetric.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ThemeMetric.h b/src/ThemeMetric.h index 5ef34f9abe..a4073ffa1a 100644 --- a/src/ThemeMetric.h +++ b/src/ThemeMetric.h @@ -21,7 +21,7 @@ public: template struct ThemeMetricTypeTraits { - enum { Callable = 1 }; + enum { Callable = 1 }; }; /* LuaReference and apActorCommands return the function directly without calling it. */ @@ -68,7 +68,7 @@ public: { ThemeManager::Subscribe( this ); } - + ~ThemeMetric() { ThemeManager::Unsubscribe( this ); @@ -131,7 +131,7 @@ public: * @brief Retrieve the metric's group. * @return the metric's group. */ const RString &GetGroup() const { return m_sGroup; } - + /** * @brief Retrieve the metric's value. * @return the metric's value. */ @@ -154,7 +154,7 @@ public: return m_currentValue; } - + operator const T& () const { return GetValue(); @@ -162,7 +162,8 @@ public: bool IsLoaded() const { return m_Value.IsSet(); } - //Hacks for VC6 for all boolean operators. + // Hacks for VC6 for all boolean operators. + // todo: get rid of these -aj bool operator ! () const { return !GetValue(); } bool operator && ( const T& input ) const { return GetValue() && input; } bool operator || ( const T& input ) const { return GetValue() || input; } From 1bf99bd528a870cf2aedda0cc1498ebefd6e6a25 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Wed, 11 May 2011 20:53:40 +0700 Subject: [PATCH 071/333] [splittiming] make screenedit work with the steps' timing. --- src/ArrowEffects.cpp | 12 ++-- src/GameState.cpp | 17 ++--- src/GameState.h | 2 - src/ScreenEdit.cpp | 168 +++++++++++++++++++++---------------------- src/SongPosition.cpp | 11 +++ src/SongPosition.h | 2 + 6 files changed, 107 insertions(+), 105 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 69372078cd..f5ea953136 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -177,7 +177,7 @@ void ArrowEffects::Update() // Update Beat do { float fAccelTime = 0.2f, fTotalTime = 0.5f; - float fBeat = GAMESTATE->m_fSongBeatVisible + fAccelTime; + float fBeat = GAMESTATE->m_pPlayerState[pn]->m_Position.m_fSongBeatVisible + fAccelTime; const bool bEvenBeat = ( int(fBeat) % 2 ) != 0; @@ -223,7 +223,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float * entirely time spacing (respectively). Occasionally, we tween between them. */ if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 1.0f ) { - float fSongBeat = GAMESTATE->m_fSongBeatVisible; + float fSongBeat = pPlayerState->m_Position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); @@ -231,7 +231,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) { - float fSongSeconds = GAMESTATE->m_fMusicSecondsVisible; + float fSongSeconds = pPlayerState->m_Position.m_fMusicSecondsVisible; float fNoteSeconds = GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; @@ -515,7 +515,7 @@ float ArrowEffects::GetRotationZ( const PlayerState* pPlayerState, float fNoteBe // As usual, enable dizzy hold heads at your own risk. -Wolfman2000 if( fEffects[PlayerOptions::EFFECT_DIZZY] != 0 && ( DIZZY_HOLD_HEADS || !bIsHoldHead ) ) { - const float fSongBeat = GAMESTATE->m_fSongBeatVisible; + const float fSongBeat = pPlayerState->m_Position.m_fSongBeatVisible; float fDizzyRotation = fNoteBeat - fSongBeat; fDizzyRotation *= fEffects[PlayerOptions::EFFECT_DIZZY]; fDizzyRotation = fmodf( fDizzyRotation, 2*PI ); @@ -532,7 +532,7 @@ float ArrowEffects::ReceptorGetRotationZ( const PlayerState* pPlayerState ) if( fEffects[PlayerOptions::EFFECT_CONFUSION] != 0 ) { - float fConfRotation = GAMESTATE->m_fSongBeatVisible; + float fConfRotation = pPlayerState->m_Position.m_fSongBeatVisible; fConfRotation *= fEffects[PlayerOptions::EFFECT_CONFUSION]; fConfRotation = fmodf( fConfRotation, 2*PI ); fConfRotation *= -180/PI; @@ -684,7 +684,7 @@ float ArrowEffects::GetBrightness( const PlayerState* pPlayerState, float fNoteB if( GAMESTATE->IsEditing() ) return 1; - float fSongBeat = GAMESTATE->m_fSongBeatVisible; + float fSongBeat = pPlayerState->m_Position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fBrightness = SCALE( fBeatsUntilStep, 0, -1, 1.f, 0.f ); diff --git a/src/GameState.cpp b/src/GameState.cpp index 54330d8dfd..4dfbd0ebe6 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -895,8 +895,6 @@ void GameState::ResetMusicStatistics() { m_Position.Reset(); - m_fMusicSecondsVisible = 0; - m_fSongBeatVisible = 0; Actor::SetBGMTime( 0, 0, 0, 0 ); FOREACH_PlayerNumber( p ) @@ -942,23 +940,16 @@ void GameState::ResetStageStatistics() m_iStageSeed = rand(); } -static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); - void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) { m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); FOREACH_EnabledPlayer( pn ) - m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); - - m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); - float fThrowAway, fThrowAway2; - bool bThrowAway; - int iThrowAway; - timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); + if( m_pCurSteps[pn] ) + m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); - Actor::SetBGMTime( GAMESTATE->m_fMusicSecondsVisible, GAMESTATE->m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); + Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } @@ -2253,7 +2244,7 @@ public: DEFINE_METHOD( IsEventMode, IsEventMode() ) DEFINE_METHOD( GetNumPlayersEnabled, GetNumPlayersEnabled() ) DEFINE_METHOD( GetSongBeat, m_Position.m_fSongBeat ) - DEFINE_METHOD( GetSongBeatVisible, m_fSongBeatVisible ) + DEFINE_METHOD( GetSongBeatVisible, m_Position.m_fSongBeatVisible ) DEFINE_METHOD( GetSongBPS, m_Position.m_fCurBPS ) DEFINE_METHOD( GetSongFreeze, m_Position.m_bFreeze ) DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay ) diff --git a/src/GameState.h b/src/GameState.h index f0446c28b8..9b192156c3 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -196,8 +196,6 @@ public: // Music statistics: SongPosition m_Position; - float m_fMusicSecondsVisible; - float m_fSongBeatVisible; BroadcastOnChange m_bGameplayLeadIn; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 929bc974cc..60d90a09d9 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -725,7 +725,7 @@ void ScreenEdit::Init() GAMESTATE->m_Position.m_fSongBeat = 0; FOREACH_PlayerNumber( p ) GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = 0; - m_fTrailingBeat = GAMESTATE->m_Position.m_fSongBeat; + m_fTrailingBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; m_iShiftAnchor = -1; m_iStartPlayingAt = -1; @@ -929,12 +929,12 @@ void ScreenEdit::Update( float fDeltaTime ) continue; float fStartPlayingAtBeat = NoteRowToBeat(m_iStartPlayingAt); - if( GAMESTATE->m_Position.m_fSongBeat <= fStartPlayingAtBeat ) + if( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat <= fStartPlayingAtBeat ) continue; float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld; float fStartBeat = max( fStartPlayingAtBeat, m_pSteps->m_Timing.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); - float fEndBeat = max( fStartBeat, GAMESTATE->m_Position.m_fSongBeat ); + float fEndBeat = max( fStartBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) ); // Round start and end to the nearest snap interval @@ -996,12 +996,12 @@ void ScreenEdit::Update( float fDeltaTime ) // Update trailing beat - float fDelta = GAMESTATE->m_Position.m_fSongBeat - m_fTrailingBeat; + float fDelta = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat - m_fTrailingBeat; if( fabsf(fDelta) < 10 ) - fapproach( m_fTrailingBeat, GAMESTATE->m_Position.m_fSongBeat, + fapproach( m_fTrailingBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fDeltaTime*40 / m_NoteFieldEdit.GetPlayerState()->m_PlayerOptions.GetCurrent().m_fScrollSpeed ); else - fapproach( m_fTrailingBeat, GAMESTATE->m_Position.m_fSongBeat, + fapproach( m_fTrailingBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fabsf(fDelta) * fDeltaTime*5 ); PlayTicks(); @@ -1072,8 +1072,8 @@ void ScreenEdit::UpdateTextInfo() RString sNoteType = ssprintf( NOTES.GetValue(), NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType()).c_str() ); RString sText; - sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_Position.m_fSongBeat ); - sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_Position.m_fSongBeat) ); + sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ); switch( EDIT_MODE.GetValue() ) { DEFAULT_FAIL( EDIT_MODE.GetValue() ); @@ -1143,24 +1143,24 @@ void ScreenEdit::UpdateTextInfo() void ScreenEdit::DrawPrimitives() { // HACK: Draw using the trailing beat - float fSongBeat = GAMESTATE->m_Position.m_fSongBeat; // save song beat - float fSongBeatNoOffset = GAMESTATE->m_Position.m_fSongBeatNoOffset; - float fSongBeatVisible = GAMESTATE->m_fSongBeatVisible; + float fSongBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; // save song beat + float fSongBeatNoOffset = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset; + float fSongBeatVisible = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible; if( !m_pSoundMusic->IsPlaying() ) { - GAMESTATE->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect - GAMESTATE->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect - GAMESTATE->m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect } ScreenWithMenuElements::DrawPrimitives(); if( !m_pSoundMusic->IsPlaying() ) { - GAMESTATE->m_Position.m_fSongBeat = fSongBeat; // restore real song beat - GAMESTATE->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; - GAMESTATE->m_fSongBeatVisible = fSongBeatVisible; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = fSongBeat; // restore real song beat + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible = fSongBeatVisible; } } @@ -1245,7 +1245,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) m_iShiftAnchor = -1; return; } - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator; switch( EditB ) { @@ -1271,7 +1271,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) ShiftToRightSide( iCol, m_NoteDataEdit.GetNumTracks() ); - const float fSongBeat = GAMESTATE->m_Position.m_fSongBeat; + const float fSongBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; const int iSongIndex = BeatToNoteRow( fSongBeat ); if( iCol >= m_NoteDataEdit.GetNumTracks() ) // this button is not in the range of columns for this Style @@ -1409,7 +1409,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( m_PlayerStateEdit.m_PlayerOptions.GetSong().m_fScrolls[PlayerOptions::SCROLL_REVERSE] > 0.5 ) fBeatsToMove *= -1; - float fDestinationBeat = GAMESTATE->m_Position.m_fSongBeat + fBeatsToMove; + float fDestinationBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat + fBeatsToMove; fDestinationBeat = Quantize( fDestinationBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); ScrollTo( fDestinationBeat ); @@ -1417,28 +1417,28 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_SCROLL_NEXT_MEASURE: { - float fDestinationBeat = GAMESTATE->m_Position.m_fSongBeat + beatsPerMeasure; + float fDestinationBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat + beatsPerMeasure; fDestinationBeat = ftruncf( fDestinationBeat, (float)beatsPerMeasure ); ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_PREV_MEASURE: { - float fDestinationBeat = QuantizeUp( GAMESTATE->m_Position.m_fSongBeat, (float)beatsPerMeasure ); + float fDestinationBeat = QuantizeUp( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, (float)beatsPerMeasure ); fDestinationBeat -= (float)beatsPerMeasure; ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_NEXT: { - int iRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); + int iRow = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); NoteDataUtil::GetNextEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } break; case EDIT_BUTTON_SCROLL_PREV: { - int iRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); + int iRow = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); NoteDataUtil::GetPrevEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } @@ -1446,13 +1446,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_LABEL_NEXT: { ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ); + GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ); } break; case EDIT_BUTTON_LABEL_PREV: { ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ); + GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ); } break; case EDIT_BUTTON_SNAP_NEXT: @@ -1465,11 +1465,11 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_LAY_SELECT: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iBeginMarker==-1 && m_NoteFieldEdit.m_iEndMarker==-1 ) { // lay begin marker - m_NoteFieldEdit.m_iBeginMarker = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + m_NoteFieldEdit.m_iBeginMarker = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); } else if( m_NoteFieldEdit.m_iEndMarker==-1 ) // only begin marker is laid { @@ -1581,7 +1581,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_BPM_UP: case EDIT_BUTTON_BPM_DOWN: { - float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat ); + float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); float fDelta; switch( EditB ) { @@ -1602,7 +1602,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } float fNewBPM = fBPM + fDelta; - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat, fNewBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fNewBPM ); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1631,7 +1631,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) + if( m_pSteps->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) break; } @@ -1639,7 +1639,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // create a new StopSegment if( fDelta > 0 ) - m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), fDelta) ); + m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), fDelta) ); } else // StopSegment being modified is m_SongTiming.m_StopSegments[i] { @@ -1809,7 +1809,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) BackgroundChange bgChange; FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(g_CurrentBGChangeLayer), bgc ) { - if( bgc->m_fStartBeat == GAMESTATE->m_Position.m_fSongBeat ) + if( bgc->m_fStartBeat == GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) { bAlreadyBGChangeHere = true; bgChange = *bgc; @@ -1902,7 +1902,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( pCourse == NULL ) break; CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; - float fStartTime = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_Position.m_fSongBeat ); + float fStartTime = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); int iAttack = FindAttackAtTime( ce.attacks, fStartTime ); if( iAttack >= 0 ) @@ -2014,12 +2014,12 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { if( g_iDefaultRecordLength.Get() == -1 ) { - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() + 1 ); } else { - m_iStartPlayingAt = BeatToNoteRow( ftruncf(GAMESTATE->m_Position.m_fSongBeat, g_iDefaultRecordLength.Get()) ); + m_iStartPlayingAt = BeatToNoteRow( ftruncf(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, g_iDefaultRecordLength.Get()) ); m_iStopPlayingAt = m_iStartPlayingAt + BeatToNoteRow( g_iDefaultRecordLength.Get() ); } @@ -2036,7 +2036,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } break; case EDIT_BUTTON_RECORD_FROM_CURSOR: - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() ); TransitionEditState( STATE_RECORDING ); break; @@ -2105,7 +2105,7 @@ void ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB ) } // Add a tap - float fBeat = GAMESTATE->m_Position.m_fSongBeat; + float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; fBeat = Quantize( fBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); const int iRow = BeatToNoteRow( fBeat ); @@ -2241,7 +2241,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB ) { case EDIT_BUTTON_RETURN_TO_EDIT: /* When exiting play mode manually, leave the cursor where it is. */ - m_fBeatToReturnTo = GAMESTATE->m_Position.m_fSongBeat; + m_fBeatToReturnTo = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; TransitionEditState( STATE_EDITING ); break; case EDIT_BUTTON_OFFSET_UP: @@ -2312,7 +2312,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_EDITING: // If exiting EDIT mode, save the cursor position. - m_fBeatToReturnTo = GAMESTATE->m_Position.m_fSongBeat; + m_fBeatToReturnTo = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; break; case STATE_PLAYING: @@ -2365,14 +2365,14 @@ void ScreenEdit::TransitionEditState( EditState em ) m_Foreground.Unload(); // Restore the cursor position. - GAMESTATE->m_Position.m_fSongBeat = m_fBeatToReturnTo; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fBeatToReturnTo; // Make sure we're snapped. - GAMESTATE->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); /* Playing and recording have lead-ins, which may start before beat 0; * make sure we don't stay there if we escaped out early. */ - GAMESTATE->m_Position.m_fSongBeat = max( GAMESTATE->m_Position.m_fSongBeat, 0 ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = max( GAMESTATE->m_Position.m_fSongBeat, 0 ); break; @@ -2465,7 +2465,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_PLAYING: case STATE_RECORDING: - const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_Position.m_fSongBeat); + const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); LOG->Trace( "Starting playback at %f", fStartSeconds ); RageSoundParams p; @@ -2485,11 +2485,11 @@ void ScreenEdit::ScrollTo( float fDestinationBeat ) CLAMP( fDestinationBeat, 0, GetMaximumBeatForMoving() ); // Don't play the sound and do the hold note logic below if our position didn't change. - const float fOriginalBeat = GAMESTATE->m_Position.m_fSongBeat; + const float fOriginalBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; if( fOriginalBeat == fDestinationBeat ) return; - GAMESTATE->m_Position.m_fSongBeat = fDestinationBeat; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = fDestinationBeat; // check to see if they're holding a button for( int n=0; n 0 ) - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_Position.m_fSongBeat, fBPM ); + m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, fStop ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, fDelay, true ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2651,7 +2651,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = atoi( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_Position.m_fSongBeat, iNum ); + m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iNum ); } SetDirty( true ); } @@ -2660,7 +2660,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = atoi( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_Position.m_fSongBeat, iDen ); + m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iDen ); } SetDirty( true ); } @@ -2669,7 +2669,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_Position.m_fSongBeat, iTick ); + m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iTick ); } SetDirty( true ); } @@ -2678,7 +2678,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_Position.m_fSongBeat, iCombo ); + m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iCombo ); } SetDirty( true ); } @@ -2689,14 +2689,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_Position.m_fSongBeat, sLabel ); + m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_Position.m_fSongBeat, fWarp ); + m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -2924,12 +2924,12 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { /* When another screen comes up, RageSounds takes over the sound timer. When we come * back, put the timer back to where it was. */ - GAMESTATE->m_Position.m_fSongBeat = m_fTrailingBeat; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fTrailingBeat; } else if( SM == SM_LoseFocus ) { // Snap the trailing beat, in case we lose focus while tweening. - m_fTrailingBeat = GAMESTATE->m_Position.m_fSongBeat; + m_fTrailingBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; } ScreenWithMenuElements::HandleScreenMessage( SM ); @@ -2940,10 +2940,10 @@ void ScreenEdit::OnSnapModeChange() m_soundChangeSnap.Play(); NoteType nt = m_SnapDisplay.GetNoteType(); - int iStepIndex = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); + int iStepIndex = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); int iElementsPerNoteType = BeatToNoteRow( NoteTypeToBeat(nt) ); int iStepIndexHangover = iStepIndex % iElementsPerNoteType; - GAMESTATE->m_Position.m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); } @@ -3090,14 +3090,14 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case play_current_beat_to_end: { - m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + m_iStartPlayingAt = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); m_iStopPlayingAt = max( m_iStartPlayingAt, m_NoteDataEdit.GetLastRow() ); TransitionEditState( STATE_PLAYING ); } break; case set_selection_start: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iEndMarker!=-1 && iCurrentRow >= m_NoteFieldEdit.m_iEndMarker ) { SCREENMAN->PlayInvalidSound(); @@ -3111,7 +3111,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case set_selection_end: { - const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat); + const int iCurrentRow = BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); if( m_NoteFieldEdit.m_iBeginMarker!=-1 && iCurrentRow <= m_NoteFieldEdit.m_iBeginMarker ) { SCREENMAN->PlayInvalidSound(); @@ -3258,7 +3258,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns case edit_timing_data: { TimingData pTime = m_pSteps->m_Timing; - const float fBeat = GAMESTATE->m_Position.m_fSongBeat; + const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); @@ -3363,7 +3363,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns { DEFAULT_FAIL( c ); case paste_at_current_beat: - iDestFirstRow = BeatToNoteRow( GAMESTATE->m_Position.m_fSongBeat ); + iDestFirstRow = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); break; case paste_at_begin_marker: ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 ); @@ -3541,16 +3541,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns TransitionEditState( STATE_RECORDING ); break; case insert_and_shift: - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case delete_and_shift: - NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_forward: - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case shift_pauses_backward: - m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); break; case convert_to_pause: { @@ -3578,14 +3578,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_pause_to_beat: { // TODO: Convert both Delays and Stops at once. - float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ); - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_Position.m_fSongBeat, 0 ); + float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ); + m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, 0 ); - float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_Position.m_fSongBeat) / 60; + float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) / 60; // don't move the step from where it is, just move everything later - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: @@ -3751,7 +3751,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_Position.m_fSongBeat) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ), 10 ); break; @@ -3759,7 +3759,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromStopChange, ENTER_STOP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -3767,7 +3767,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromDelayChange, ENTER_DELAY_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -3775,7 +3775,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureNumeratorChange, ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator ), 3 ); break; @@ -3783,7 +3783,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureDenominatorChange, ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iDenominator ), + ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iDenominator ), 3 ); break; @@ -3791,7 +3791,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTickcountChange, ENTER_TICKCOUNT_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ), 2 ); break; @@ -3799,7 +3799,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromComboChange, ENTER_COMBO_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_Position.m_fSongBeat ) ), + ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ), 4 ); break; @@ -3807,7 +3807,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromLabelChange, ENTER_LABEL_VALUE, - ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_Position.m_fSongBeat ).c_str() ), + ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).c_str() ), 64 ); break; @@ -3815,7 +3815,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), 10 ); break; @@ -4022,7 +4022,7 @@ void ScreenEdit::CheckNumberOfNotesAndUndo() if( EDIT_MODE.GetValue() != EditMode_Home ) return; - TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ); + TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); int rowsPerMeasure = curTime.m_iDenominator * curTime.m_iNumerator; for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure ) @@ -4074,7 +4074,7 @@ float ScreenEdit::GetMaximumBeatForNewNote() const /* Round up to the next measure end. Some songs end on weird beats * mid-measure, and it's odd to have movement capped to these weird * beats. */ - int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat ).m_iNumerator; + int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator; fEndBeat += beatsPerMeasure; fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure ); diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 14a67c1806..048c93708c 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -1,5 +1,7 @@ #include "SongPosition.h" +static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); + void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) { @@ -43,12 +45,21 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData } } */ + + m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); + float fThrowAway, fThrowAway2; + bool bThrowAway; + int iThrowAway; + timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 ); } void SongPosition::Reset() { + m_fMusicSecondsVisible = 0; + m_fSongBeatVisible = 0; + m_fMusicSeconds = 0; // MUSIC_SECONDS_INVALID; // todo: move me to FOREACH_EnabledPlayer( p ) after [NUM_PLAYERS]ing m_fSongBeat = 0; diff --git a/src/SongPosition.h b/src/SongPosition.h index abe1dc2a8e..56cf0e38d5 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -31,6 +31,8 @@ class SongPosition /** @brief The beat to warp to afterwards. */ float m_fWarpDestination; RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update + float m_fMusicSecondsVisible; + float m_fSongBeatVisible; void Reset(); void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); From 378b4383895dd62dc27628f1c4c9cc335f588dcd Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Wed, 11 May 2011 21:22:18 +0700 Subject: [PATCH 072/333] [splittiming] screenedit now behaves (just moving around, charting process not tested) some work need to be done on snapping and transitioning between editing and playing. --- src/ScreenEdit.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 60d90a09d9..76ae67a362 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1142,26 +1142,30 @@ void ScreenEdit::UpdateTextInfo() void ScreenEdit::DrawPrimitives() { - // HACK: Draw using the trailing beat - float fSongBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; // save song beat - float fSongBeatNoOffset = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset; - float fSongBeatVisible = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible; - if( !m_pSoundMusic->IsPlaying() ) + if( m_pSoundMusic->IsPlaying() ) { - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect + ScreenWithMenuElements::DrawPrimitives(); + return; } + // HACK: Draw using the trailing beat + PlayerState *pPlayerState = const_cast (m_NoteFieldEdit.GetPlayerState()); + + float fSongBeat = pPlayerState->m_Position.m_fSongBeat; // save song beat + float fSongBeatNoOffset = pPlayerState->m_Position.m_fSongBeatNoOffset; + float fSongBeatVisible = pPlayerState->m_Position.m_fSongBeatVisible; + + pPlayerState->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect + pPlayerState->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect + pPlayerState->m_Position.m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect + ScreenWithMenuElements::DrawPrimitives(); - if( !m_pSoundMusic->IsPlaying() ) - { - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = fSongBeat; // restore real song beat - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeatVisible = fSongBeatVisible; - } + pPlayerState->m_Position.m_fSongBeat = fSongBeat; // restore real song beat + pPlayerState->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; + pPlayerState->m_Position.m_fSongBeatVisible = fSongBeatVisible; + } void ScreenEdit::Input( const InputEventPlus &input ) From 33172945ea0e1688b52e4a28785d4f5e2478f2d6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 11:03:12 -0400 Subject: [PATCH 073/333] [splittiming] Players, invalidate your caches! --- src/Song.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index c5986b0284..47c84ed8b3 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 171; +const int FILE_CACHE_VERSION = 172; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; From a8f2d0094fcf627edd65e33f7cd5b424c5fcced2 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Wed, 11 May 2011 22:08:38 +0700 Subject: [PATCH 074/333] [splittiming] I accidently hardcoded PLAYER_1 in NoteField --- src/NoteField.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 72a9ceb90e..5f76e23d3e 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -742,7 +742,7 @@ void NoteField::DrawPrimitives() // Draw beat bars if( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) { - const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing.m_vTimeSignatureSegments; + const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing.m_vTimeSignatureSegments; int iMeasureIndex = 0; FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter ) { @@ -785,7 +785,7 @@ void NoteField::DrawPrimitives() { ASSERT(GAMESTATE->m_pCurSong); - const TimingData &timing = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing; + const TimingData &timing = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing; // BPM text FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg ) From a47830834555725e203c6c709c8824d2af34558f Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Wed, 11 May 2011 22:57:55 +0700 Subject: [PATCH 075/333] [splittiming] Fix crash. I don't know what caused it and how it was caused, but this fixed it. --- src/PlayerOptions.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PlayerOptions.h b/src/PlayerOptions.h index 8a66d1d758..c6ea986160 100644 --- a/src/PlayerOptions.h +++ b/src/PlayerOptions.h @@ -35,8 +35,9 @@ public: m_fPassmark(0), m_SpeedfPassmark(1.0f), m_fRandomSpeed(0), m_SpeedfRandomSpeed(1.0f), m_bMuteOnError(false), m_FailType(FAIL_IMMEDIATE), - m_ScoreDisplay(SCORING_ADD), m_sNoteSkin("") + m_ScoreDisplay(SCORING_ADD) { + m_sNoteSkin = ""; ZERO( m_fAccels ); ONE( m_SpeedfAccels ); ZERO( m_fEffects ); ONE( m_SpeedfEffects ); ZERO( m_fAppearances ); ONE( m_SpeedfAppearances ); From 212a3b971fd53db68bd591b4636b827aeb70e05f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 14:33:04 -0400 Subject: [PATCH 076/333] Allow beat versus to take place. Made sure to cover 5 and 7 styles. --- src/GameConstantsAndTypes.h | 2 + src/GameManager.cpp | 91 ++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/GameConstantsAndTypes.h b/src/GameConstantsAndTypes.h index 92b19f1fc7..7242f4009d 100644 --- a/src/GameConstantsAndTypes.h +++ b/src/GameConstantsAndTypes.h @@ -87,8 +87,10 @@ enum StepsType StepsType_para_single, StepsType_ds3ddx_single, StepsType_beat_single5, + StepsType_beat_versus5, StepsType_beat_double5, StepsType_beat_single7, + StepsType_beat_versus7, StepsType_beat_double7, StepsType_maniax_single, StepsType_maniax_double, diff --git a/src/GameManager.cpp b/src/GameManager.cpp index 6a7043d278..8709814bdd 100644 --- a/src/GameManager.cpp +++ b/src/GameManager.cpp @@ -1584,7 +1584,47 @@ static const Style g_Style_Beat_Single5 = false, // m_bLockDifficulties }; -static const Style g_Style_Beat_Double = +static const Style g_Style_Beat_Versus5 = +{ // STYLE_BEAT_VERSUS + true, // m_bUsedForGameplay + false, // m_bUsedForEdit + true, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "versus", // m_szName + StepsType_beat_versus5, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 6, // m_iColsPerPlayer + { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; + { // PLAYER_1 + { TRACK_1, -BEAT_COL_SPACING*2.5f, NULL }, + { TRACK_2, -BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_3, -BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_4, +BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_5, +BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_6, +BEAT_COL_SPACING*3.0f, "scratch" }, + }, + { // PLAYER_2 + { TRACK_1, -BEAT_COL_SPACING*2.5f, NULL }, + { TRACK_2, -BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_3, -BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_4, +BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_5, +BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_6, +BEAT_COL_SPACING*3.0f, "scratch" }, + }, + }, + { // m_iInputColumn[NUM_GameController][NUM_GameButton] + { 0, 1, 2, 3, 4, Style::NO_MAPPING, Style::NO_MAPPING, 5, 5, Style::END_MAPPING }, + { 0, 1, 2, 3, 4, Style::NO_MAPPING, Style::NO_MAPPING, 5, 5, Style::END_MAPPING } + }, + { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; + 0,1,2,3,4,5 + }, + false, // m_bNeedsZoomOutWith2Players + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties +}; + +static const Style g_Style_Beat_Double5 = { // STYLE_BEAT_DOUBLE true, // m_bUsedForGameplay true, // m_bUsedForEdit @@ -1680,6 +1720,51 @@ static const Style g_Style_Beat_Single7 = false, // m_bLockDifficulties }; +static const Style g_Style_Beat_Versus7 = +{ // STYLE_BEAT_VERSUS7 + true, // m_bUsedForGameplay + true, // m_bUsedForEdit + false, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "single7", // m_szName + StepsType_beat_versus7, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 8, // m_iColsPerPlayer + { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; + { // PLAYER_1 + { TRACK_8, -BEAT_COL_SPACING*3.5f, "scratch" }, + { TRACK_1, -BEAT_COL_SPACING*2.0f, NULL }, + { TRACK_2, -BEAT_COL_SPACING*1.0f, NULL }, + { TRACK_3, -BEAT_COL_SPACING*0.0f, NULL }, + { TRACK_4, +BEAT_COL_SPACING*1.0f, NULL }, + { TRACK_5, +BEAT_COL_SPACING*2.0f, NULL }, + { TRACK_6, +BEAT_COL_SPACING*3.0f, NULL }, + { TRACK_7, +BEAT_COL_SPACING*4.0f, NULL }, + }, + { // PLAYER_2 + { TRACK_1, -BEAT_COL_SPACING*3.5f, NULL }, + { TRACK_2, -BEAT_COL_SPACING*2.5f, NULL }, + { TRACK_3, -BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_4, -BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_5, +BEAT_COL_SPACING*0.5f, NULL }, + { TRACK_6, +BEAT_COL_SPACING*1.5f, NULL }, + { TRACK_7, +BEAT_COL_SPACING*2.5f, NULL }, + { TRACK_8, +BEAT_COL_SPACING*4.0f, "scratch" }, + }, + }, + { // m_iInputColumn[NUM_GameController][NUM_GameButton] + { 1, 2, 3, 4, 5, 6, 7, 0, 0, Style::END_MAPPING }, + { 0, 1, 2, 3, 4, 5, 6, 7, 7, Style::END_MAPPING }, + }, + { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; + 0,1,2,3,4,5,6,7 + }, + false, // m_bNeedsZoomOutWith2Players + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties +}; + + static const Style g_Style_Beat_Double7 = { // STYLE_BEAT_DOUBLE7 true, // m_bUsedForGameplay @@ -1743,8 +1828,10 @@ static const Style g_Style_Beat_Double7 = static const Style *g_apGame_Beat_Styles[] = { &g_Style_Beat_Single5, - &g_Style_Beat_Double, + &g_Style_Beat_Versus5, + &g_Style_Beat_Double5, &g_Style_Beat_Single7, + &g_Style_Beat_Versus7, &g_Style_Beat_Double7, NULL }; From da51e26d07617f88fb2f4b8d0c5966e247b45a24 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 15:58:31 -0400 Subject: [PATCH 077/333] Standardize conversion processes. Too many arguments for or against the many methods: stick to one inside a common function. This commit will force recompilation of many files. --- src/BGAnimationLayer.cpp | 8 ++++---- src/CourseLoaderCRS.cpp | 20 ++++++++++---------- src/FileDownload.cpp | 6 +++--- src/Font.cpp | 4 ++-- src/GameCommand.cpp | 4 ++-- src/GameState.cpp | 2 +- src/LuaManager.cpp | 2 +- src/NoteSkinManager.cpp | 5 +++-- src/NotesLoaderBMS.cpp | 16 ++++++++-------- src/NotesLoaderDWI.cpp | 4 ++-- src/NotesLoaderKSF.cpp | 8 ++++---- src/NotesLoaderPMS.cpp | 16 ++++++++-------- src/NotesLoaderSM.cpp | 20 ++++++++++---------- src/NotesLoaderSMA.cpp | 8 ++++---- src/NotesLoaderSSC.cpp | 24 ++++++++++++------------ src/OptionRowHandler.cpp | 6 +++--- src/PlayerOptions.cpp | 2 +- src/Profile.cpp | 2 +- src/ProfileManager.cpp | 2 +- src/RageBitmapTexture.cpp | 4 ++-- src/RageTexture.cpp | 4 ++-- src/RageUtil.cpp | 21 ++++++++++++++++++--- src/RageUtil.h | 10 ++++++++++ src/ScreenEdit.cpp | 12 +++++------- src/ScreenGameplay.cpp | 2 +- src/ScreenMiniMenu.h | 5 +---- src/ScreenPackages.cpp | 6 +++--- src/SongOptions.cpp | 2 +- src/XmlFile.cpp | 4 ++-- 29 files changed, 125 insertions(+), 104 deletions(-) diff --git a/src/BGAnimationLayer.cpp b/src/BGAnimationLayer.cpp index 1d78d92d73..7f9e80e84c 100644 --- a/src/BGAnimationLayer.cpp +++ b/src/BGAnimationLayer.cpp @@ -388,7 +388,7 @@ void BGAnimationLayer::LoadFromNode( const XNode* pNode ) pNode->GetAttrValue( "Stretch", bStretch ); // Check for string match first, then do integer match. - // "if(atoi(type)==0)" was matching against all string matches. + // "if(StringType(type)==0)" was matching against all string matches. // -Chris if( stricmp(type,"sprite")==0 ) { @@ -402,16 +402,16 @@ void BGAnimationLayer::LoadFromNode( const XNode* pNode ) { m_Type = TYPE_TILES; } - else if( atoi(type) == 1 ) + else if( StringToInt(type) == 1 ) { m_Type = TYPE_SPRITE; bStretch = true; } - else if( atoi(type) == 2 ) + else if( StringToInt(type) == 2 ) { m_Type = TYPE_PARTICLES; } - else if( atoi(type) == 3 ) + else if( StringToInt(type) == 3 ) { m_Type = TYPE_TILES; } diff --git a/src/CourseLoaderCRS.cpp b/src/CourseLoaderCRS.cpp index e2bd6a59a4..e91d772737 100644 --- a/src/CourseLoaderCRS.cpp +++ b/src/CourseLoaderCRS.cpp @@ -85,7 +85,7 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou } else if( 0 == stricmp(sValueName, "LIVES") ) { - out.m_iLives = max( atoi(sParams[1]), 0 ); + out.m_iLives = max( StringToInt(sParams[1]), 0 ); } else if( 0 == stricmp(sValueName, "GAINSECONDS") ) { @@ -95,7 +95,7 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou { if( sParams.params.size() == 2 ) { - out.m_iCustomMeter[Difficulty_Medium] = max( atoi(sParams[1]), 0 ); /* compat */ + out.m_iCustomMeter[Difficulty_Medium] = max( StringToInt(sParams[1]), 0 ); /* compat */ } else if( sParams.params.size() == 3 ) { @@ -105,7 +105,7 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou LOG->UserLog( "Course file", sPath, "contains an invalid #METER string: \"%s\"", sParams[1].c_str() ); continue; } - out.m_iCustomMeter[cd] = max( atoi(sParams[2]), 0 ); + out.m_iCustomMeter[cd] = max( StringToInt(sParams[2]), 0 ); } } // todo: add COMBO and COMBOMODE from DWI CRS files? -aj @@ -167,28 +167,28 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou // most played if( sParams[1].Left(strlen("BEST")) == "BEST" ) { - new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("BEST")) ) - 1; + new_entry.iChooseIndex = StringToInt( sParams[1].Right(sParams[1].size()-strlen("BEST")) ) - 1; CLAMP( new_entry.iChooseIndex, 0, 500 ); new_entry.songSort = SongSort_MostPlays; } // least played else if( sParams[1].Left(strlen("WORST")) == "WORST" ) { - new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("WORST")) ) - 1; + new_entry.iChooseIndex = StringToInt( sParams[1].Right(sParams[1].size()-strlen("WORST")) ) - 1; CLAMP( new_entry.iChooseIndex, 0, 500 ); new_entry.songSort = SongSort_FewestPlays; } // best grades else if( sParams[1].Left(strlen("GRADEBEST")) == "GRADEBEST" ) { - new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("GRADEBEST")) ) - 1; + new_entry.iChooseIndex = StringToInt( sParams[1].Right(sParams[1].size()-strlen("GRADEBEST")) ) - 1; CLAMP( new_entry.iChooseIndex, 0, 500 ); new_entry.songSort = SongSort_TopGrades; } // worst grades else if( sParams[1].Left(strlen("GRADEWORST")) == "GRADEWORST" ) { - new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("GRADEWORST")) ) - 1; + new_entry.iChooseIndex = StringToInt( sParams[1].Right(sParams[1].size()-strlen("GRADEWORST")) ) - 1; CLAMP( new_entry.iChooseIndex, 0, 500 ); new_entry.songSort = SongSort_LowestGrades; } @@ -284,7 +284,7 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou else if( !sMod.CompareNoCase("nodifficult") ) new_entry.bNoDifficult = true; else if( sMod.length() > 5 && !sMod.Left(5).CompareNoCase("award") ) - new_entry.iGainLives = atoi( sMod.substr(5).c_str() ); + new_entry.iGainLives = StringToInt( sMod.substr(5) ); else continue; mods.erase( mods.begin() + j ); @@ -306,8 +306,8 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou else if( bFromCache && !stricmp(sValueName, "RADAR") ) { - StepsType st = (StepsType) atoi(sParams[1]); - CourseDifficulty cd = (CourseDifficulty) atoi( sParams[2] ); + StepsType st = (StepsType) StringToInt(sParams[1]); + CourseDifficulty cd = (CourseDifficulty) StringToInt( sParams[2] ); RadarValues rv; rv.FromString( sParams[3] ); diff --git a/src/FileDownload.cpp b/src/FileDownload.cpp index 3f725895b3..80422684c2 100644 --- a/src/FileDownload.cpp +++ b/src/FileDownload.cpp @@ -272,14 +272,14 @@ void FileTransfer::HTTPUpdate() m_sResponseName = "Malformed response."; return; } - m_iResponseCode = atoi(m_sBUFFER.substr(i+1,j-i).c_str()); + m_iResponseCode = StringToInt(m_sBUFFER.substr(i+1,j-i)); m_sResponseName = m_sBUFFER.substr( j+1, k-j ); i = m_sBUFFER.find("Content-Length:"); j = m_sBUFFER.find("\n", i+1 ); if( i != string::npos ) - m_iTotalBytes = atoi(m_sBUFFER.substr(i+16,j-i).c_str()); + m_iTotalBytes = StringToInt(m_sBUFFER.substr(i+16,j-i)); else m_iTotalBytes = -1; // We don't know, so go until disconnect @@ -350,7 +350,7 @@ bool FileTransfer::ParseHTTPAddress( const RString &URL, RString &sProto, RStrin sServer = asMatches[1]; if( asMatches[3] != "" ) { - iPort = atoi(asMatches[3]); + iPort = StringToInt(asMatches[3]); if( iPort == 0 ) return false; } diff --git a/src/Font.cpp b/src/Font.cpp index a012906df5..406aaf7d9f 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -414,7 +414,7 @@ void Font::LoadFontPageSettings( FontPageSettings &cfg, IniFile &ini, const RStr // If val is an integer, it's a width, eg. "10=27". if( IsAnInt(sName) ) { - cfg.m_mapGlyphWidths[atoi(sName)] = pValue->GetValue(); + cfg.m_mapGlyphWidths[StringToInt(sName)] = pValue->GetValue(); continue; } @@ -516,7 +516,7 @@ void Font::LoadFontPageSettings( FontPageSettings &cfg, IniFile &ini, const RStr TrimLeft( sRowStr ); ASSERT( IsAnInt(sRowStr) ); - const int iRow = atoi( sRowStr.c_str() ); + const int iRow = StringToInt( sRowStr ); const int iFirstFrame = iRow * iNumFramesWide; if( iRow > iNumFramesHigh ) diff --git a/src/GameCommand.cpp b/src/GameCommand.cpp index 2341aaa088..0f6ac72104 100644 --- a/src/GameCommand.cpp +++ b/src/GameCommand.cpp @@ -335,12 +335,12 @@ void GameCommand::LoadOne( const Command& cmd ) else if( sName == "weight" ) { - m_iWeightPounds = atoi( sValue ); + m_iWeightPounds = StringToInt( sValue ); } else if( sName == "goalcalories" ) { - m_iGoalCalories = atoi( sValue ); + m_iGoalCalories = StringToInt( sValue ); } else if( sName == "goaltype" ) diff --git a/src/GameState.cpp b/src/GameState.cpp index 90792cad8c..bd4188df15 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -209,7 +209,7 @@ void GameState::ApplyCmdline() RString sPlayer; for( int i = 0; GetCommandlineArgument( "player", &sPlayer, i ); ++i ) { - int pn = atoi( sPlayer )-1; + int pn = StringToInt( sPlayer )-1; if( !IsAnInt( sPlayer ) || pn < 0 || pn >= NUM_PLAYERS ) RageException::Throw( "Invalid argument \"--player=%s\".", sPlayer.c_str() ); diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index e61352d9c0..97ab18b552 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -11,7 +11,7 @@ #include "Command.h" #include "RageTypes.h" -#include +#include // conversion for lua functions. #include #include #include diff --git a/src/NoteSkinManager.cpp b/src/NoteSkinManager.cpp index e63e99e35a..1f285a5b65 100644 --- a/src/NoteSkinManager.cpp +++ b/src/NoteSkinManager.cpp @@ -251,7 +251,7 @@ RString NoteSkinManager::GetMetric( const RString &sButtonName, const RString &s int NoteSkinManager::GetMetricI( const RString &sButtonName, const RString &sValueName ) { - return atoi( GetMetric(sButtonName,sValueName) ); + return StringToInt( GetMetric(sButtonName,sValueName) ); } float NoteSkinManager::GetMetricF( const RString &sButtonName, const RString &sValueName ) @@ -261,7 +261,8 @@ float NoteSkinManager::GetMetricF( const RString &sButtonName, const RString &sV bool NoteSkinManager::GetMetricB( const RString &sButtonName, const RString &sValueName ) { - return atoi( GetMetric(sButtonName,sValueName) ) != 0; + // Could also call GetMetricI here...hmm. + return StringToInt( GetMetric(sButtonName,sValueName) ) != 0; } apActorCommands NoteSkinManager::GetMetricA( const RString &sButtonName, const RString &sValueName ) diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index d90a368591..a29c833a11 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -398,8 +398,8 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) ) continue; // this is step or offset data. Looks like "#00705" - int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); - int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1, 3) ); + int iBMSTrackNo = StringToInt( sName.substr(4, 2) ); RString nData = it->second; int totalPairs = nData.size() / 2; if( iBMSTrackNo != BMS_TRACK_TIME_SIG && iBMSTrackNo != 7 ) @@ -423,10 +423,10 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t // this is step or offset data. Looks like "#00705" const RString &sData = it->second; - int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1, 3) ); if( iMeasureNo < iStartMeasureNo ) continue; - int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() ); + int iBMSTrackNo = StringToInt( sName.substr(4, 2) ); if( iBMSTrackNo == BMS_TRACK_TIME_SIG ) out[iMeasureNo] = StringToFloat( sData ); } @@ -446,9 +446,9 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo int iPlayer = -1; RString sData; if( GetTagFromMap( mapNameToData, "#player", sData ) ) - iPlayer = atoi(sData); + iPlayer = StringToInt(sData); if( GetTagFromMap( mapNameToData, "#playlevel", sData ) ) - out.SetMeter( atoi(sData) ); + out.SetMeter( StringToInt(sData) ); NoteData ndNotes; ndNotes.SetNumTracks( NUM_BMS_TRACKS ); @@ -475,8 +475,8 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo continue; // this is step or offset data. Looks like "#00705" - int iMeasureNo = atoi( sName.substr(1,3).c_str() ); - int iRawTrackNum = atoi( sName.substr(4,2).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1,3) ); + int iRawTrackNum = StringToInt( sName.substr(4,2) ); int iRowNo = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); const RString &sNoteData = it->second; diff --git a/src/NotesLoaderDWI.cpp b/src/NotesLoaderDWI.cpp index b15c74252f..d24ea89af6 100644 --- a/src/NotesLoaderDWI.cpp +++ b/src/NotesLoaderDWI.cpp @@ -206,7 +206,7 @@ static bool LoadFromDWITokens( DEFAULT_FAIL( out.m_StepsType ); } - int iNumFeet = atoi(sNumFeet); + int iNumFeet = StringToInt(sNumFeet); // out.SetDescription(sDescription); // Don't put garbage in the description. out.SetMeter(iNumFeet); out.SetDifficulty( DwiCompatibleStringToDifficulty(sDescription) ); @@ -517,7 +517,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla else if( 0==stricmp(sValueName,"GAP") ) // the units of GAP is 1/1000 second - out.m_Timing.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f; + out.m_Timing.m_fBeat0OffsetInSeconds = -StringToInt( sParams[1] ) / 1000.0f; else if( 0==stricmp(sValueName,"SAMPLESTART") ) out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]); diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index b1732cdf81..4cfaaf0001 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -35,7 +35,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, // handle the data if( sValueName=="TICKCOUNT" ) { - iTickCount = atoi( sParams[1] ); + iTickCount = StringToInt( sParams[1] ); if( iTickCount <= 0 ) { LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount ); @@ -50,7 +50,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, } else if( sValueName=="DIFFICULTY" ) { - out.SetMeter( max(atoi(sParams[1]), 0) ); + out.SetMeter( max(StringToInt(sParams[1]), 0) ); } // new cases from Aldo_MX's fork: else if( sValueName=="PLAYER" ) @@ -190,7 +190,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, else if ( BeginsWith(sRowString, "|T") ) { RString temp = sRowString.substr(2,sRowString.size()-3); - newTick = atoi(temp); + newTick = StringToInt(temp); bTickChangeNeeded = true; continue; } @@ -401,7 +401,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant /* TICKCOUNT will be used below if there are DM compliant BPM changes * and stops. It will be called again in LoadFromKSFFile for the * actual steps. */ - iTickCount = atoi( sParams[1] ); + iTickCount = StringToInt( sParams[1] ); iTickCount = iTickCount > 0 ? iTickCount : 2; // again, Direct Move uses 4 as a default. // add a tickcount for those using the [Player] // CheckpointsUseTimeSignatures metric. -aj diff --git a/src/NotesLoaderPMS.cpp b/src/NotesLoaderPMS.cpp index 08f8efbb79..c5a3628e9a 100644 --- a/src/NotesLoaderPMS.cpp +++ b/src/NotesLoaderPMS.cpp @@ -346,8 +346,8 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t // this is step or offset data. Looks like "#00705" const RString &sData = it->second; - int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); - int iPMSTrackNo = atoi( sName.substr(4, 2).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1, 3) ); + int iPMSTrackNo = StringToInt( sName.substr(4, 2) ); if( iPMSTrackNo == PMS_TRACK_TIME_SIG ) out[iMeasureNo] = StringToFloat( sData ); } @@ -367,9 +367,9 @@ static bool LoadFromPMSFile( const RString &sPath, const NameToData_t &mapNameTo int iPlayer = -1; RString sData; if( GetTagFromMap( mapNameToData, "#player", sData ) ) - iPlayer = atoi(sData); + iPlayer = StringToInt(sData); if( GetTagFromMap( mapNameToData, "#playlevel", sData ) ) - out.SetMeter( atoi(sData) ); + out.SetMeter( StringToInt(sData) ); NoteData ndNotes; ndNotes.SetNumTracks( NUM_PMS_TRACKS ); @@ -396,8 +396,8 @@ static bool LoadFromPMSFile( const RString &sPath, const NameToData_t &mapNameTo continue; // this is step or offset data. Looks like "#00705" - int iMeasureNo = atoi( sName.substr(1,3).c_str() ); - int iRawTrackNum = atoi( sName.substr(4,2).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1,3) ); + int iRawTrackNum = StringToInt( sName.substr(4,2) ); int iRowNo = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); const RString &sNoteData = it->second; @@ -649,8 +649,8 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) ) continue; // this is step or offset data. Looks like "#00705" - int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); - int iPMSTrackNo = atoi( sName.substr(4, 2).c_str() ); + int iMeasureNo = StringToInt( sName.substr(1, 3) ); + int iPMSTrackNo = StringToInt( sName.substr(4, 2) ); int iStepIndex = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut ); float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut ); int iRowsPerMeasure = BeatToNoteRow( fBeatsPerMeasure ); diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index f1ab8ec5ad..4a2bf428f7 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -60,7 +60,7 @@ void SMLoader::LoadFromSMTokens( out.SetDifficulty( Difficulty_Challenge ); } - out.SetMeter( atoi(sMeter) ); + out.SetMeter( StringToInt(sMeter) ); vector saValues; split( sRadarValues, ",", saValues, true ); int categories = NUM_RadarCategory - 1; // Fakes aren't counted in the radar values. @@ -309,8 +309,8 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) TimeSignatureSegment seg; seg.m_iStartRow = BeatToNoteRow(fBeat); - seg.m_iNumerator = atoi( vs2[1] ); - seg.m_iDenominator = atoi( vs2[2] ); + seg.m_iNumerator = StringToInt( vs2[1] ); + seg.m_iDenominator = StringToInt( vs2[2] ); if( fBeat < 0 ) { @@ -352,7 +352,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); - int iTicks = atoi( arrayTickcountValues[1] ); + int iTicks = StringToInt( arrayTickcountValues[1] ); // you're lazy, let SM do the work for you... -DaisuMaster if( iTicks < 1) iTicks = 1; if( iTicks > ROWS_PER_BEAT ) iTicks = ROWS_PER_BEAT; @@ -411,7 +411,7 @@ bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString // Backward compatibility: if( change.m_def.m_sEffect.empty() ) { - bool bLoop = atoi( aBGChangeValues[5] ) != 0; + bool bLoop = StringToInt( aBGChangeValues[5] ) != 0; if( !bLoop ) change.m_def.m_sEffect = SBE_StretchNoLoop; } @@ -421,7 +421,7 @@ bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString // Backward compatibility: if( change.m_def.m_sEffect.empty() ) { - bool bRewindMovie = atoi( aBGChangeValues[4] ) != 0; + bool bRewindMovie = StringToInt( aBGChangeValues[4] ) != 0; if( bRewindMovie ) change.m_def.m_sEffect = SBE_StretchRewind; } @@ -430,7 +430,7 @@ bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString // param 9 overrides this. // Backward compatibility: if( change.m_sTransition.empty() ) - change.m_sTransition = (atoi( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; + change.m_sTransition = (StringToInt( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; // fall through case 3: change.m_fRate = StringToFloat( aBGChangeValues[2] ); @@ -560,12 +560,12 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else if( sValueName=="HASMUSIC" ) { if( bFromCache ) - out.m_bHasMusic = atoi( sParams[1] ) != 0; + out.m_bHasMusic = StringToInt( sParams[1] ) != 0; } else if( sValueName=="HASBANNER" ) { if( bFromCache ) - out.m_bHasBanner = atoi( sParams[1] ) != 0; + out.m_bHasBanner = StringToInt( sParams[1] ) != 0; } else if( sValueName=="SAMPLESTART" ) @@ -609,7 +609,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache * used 3.9+ features are not excluded here */ else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if( atoi(sParams[1]) > 0 ) + else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; else LOG->UserLog( "Song file", sPath, "has an unknown #SELECTABLE value, \"%s\"; ignored.", sParams[1].c_str() ); diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index dd6ce2c60f..824a526e41 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -59,7 +59,7 @@ void SMALoader::LoadFromSMATokens( out.SetDifficulty( Difficulty_Challenge ); } - out.SetMeter( atoi(sMeter) ); + out.SetMeter( StringToInt(sMeter) ); vector saValues; split( sRadarValues, ",", saValues, true ); int categories = NUM_RadarCategory - 1; // Fakes aren't counted in the radar values. @@ -257,7 +257,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) * used 3.9+ features are not excluded here */ else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if( atoi(sParams[1]) > 0 ) + else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; else LOG->UserLog( "Song file", sPath, "has an unknown #SELECTABLE value, \"%s\"; ignored.", sParams[1].c_str() ); @@ -430,13 +430,13 @@ void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) break; } encountered = true; - rowsPerMeasure = atoi( sParams[1] ); + rowsPerMeasure = StringToInt( sParams[1] ); } else if( sValueName=="BEATSPERMEASURE" ) { TimeSignatureSegment new_seg; new_seg.m_iStartRow = 0; - new_seg.m_iNumerator = atoi( sParams[1] ); + new_seg.m_iNumerator = StringToInt( sParams[1] ); new_seg.m_iDenominator = 4; out.AddTimeSignatureSegment( new_seg ); } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index a2308e9fd2..3ae4b3a0d4 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -61,7 +61,7 @@ bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGCha // Backward compatibility: if( change.m_def.m_sEffect.empty() ) { - bool bLoop = atoi( aBGChangeValues[5] ) != 0; + bool bLoop = StringToInt( aBGChangeValues[5] ) != 0; if( !bLoop ) change.m_def.m_sEffect = SBE_StretchNoLoop; } @@ -71,7 +71,7 @@ bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGCha // Backward compatibility: if( change.m_def.m_sEffect.empty() ) { - bool bRewindMovie = atoi( aBGChangeValues[4] ) != 0; + bool bRewindMovie = StringToInt( aBGChangeValues[4] ) != 0; if( bRewindMovie ) change.m_def.m_sEffect = SBE_StretchRewind; } @@ -80,7 +80,7 @@ bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGCha // param 9 overrides this. // Backward compatibility: if( change.m_sTransition.empty() ) - change.m_sTransition = (atoi( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; + change.m_sTransition = (StringToInt( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; // fall through case 3: change.m_fRate = StringToFloat( aBGChangeValues[2] ); @@ -287,7 +287,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach * used 3.9+ features are not excluded here */ else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if( atoi(sParams[1]) > 0 ) + else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; else LOG->UserLog( "Song file", sPath, "has an unknown #SELECTABLE value, \"%s\"; ignored.", sParams[1].c_str() ); @@ -570,8 +570,8 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach TimeSignatureSegment seg; seg.m_iStartRow = BeatToNoteRow(fBeat); - seg.m_iNumerator = atoi( vs2[1] ); - seg.m_iDenominator = atoi( vs2[2] ); + seg.m_iNumerator = StringToInt( vs2[1] ); + seg.m_iDenominator = StringToInt( vs2[2] ); if( fBeat < 0 ) { @@ -613,7 +613,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach } const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); - const int iTicks = atoi( arrayTickcountValues[1] ); + const int iTicks = StringToInt( arrayTickcountValues[1] ); TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks ); if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants @@ -644,7 +644,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach continue; } const float fComboBeat = StringToFloat( arrayComboValues[0] ); - const int iCombos = atoi( arrayComboValues[1] ); + const int iCombos = StringToInt( arrayComboValues[1] ); ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); out.m_Timing.AddComboSegment( new_seg ); } @@ -673,13 +673,13 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="HASMUSIC" ) { if( bFromCache ) - out.m_bHasMusic = atoi( sParams[1] ) != 0; + out.m_bHasMusic = StringToInt( sParams[1] ) != 0; } else if( sValueName=="HASBANNER" ) { if( bFromCache ) - out.m_bHasBanner = atoi( sParams[1] ) != 0; + out.m_bHasBanner = StringToInt( sParams[1] ) != 0; } // This tag will get us to the next section. @@ -714,7 +714,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="METER" ) { - pNewNotes->SetMeter( atoi( sParams[1] ) ); + pNewNotes->SetMeter( StringToInt( sParams[1] ) ); } else if( sValueName=="RADARVALUES" ) @@ -986,7 +986,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat else if( sValueName=="METER" ) { - pNewNotes->SetMeter( atoi( sParams[1] ) ); + pNewNotes->SetMeter( StringToInt( sParams[1] ) ); bSSCFormat = true; } diff --git a/src/OptionRowHandler.cpp b/src/OptionRowHandler.cpp index 64314a9cd5..00125fa6b1 100644 --- a/src/OptionRowHandler.cpp +++ b/src/OptionRowHandler.cpp @@ -154,7 +154,7 @@ public: RageException::Throw( "Parse error in \"ScreenOptionsMaster::%s\".", sParam.c_str() ); m_Def.m_bOneChoiceForAllPlayers = false; - const int NumCols = atoi( lCmds.v[0].m_vsArgs[0] ); + const int NumCols = StringToInt( lCmds.v[0].m_vsArgs[0] ); for( unsigned i=1; i= 0 && pn < NUM_PLAYERS ); m_Def.m_vEnabledForPlayers.insert( pn ); } diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 8d1a8199cd..036f1d314c 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -299,7 +299,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut { /* XXX We know what they want, is there any reason not to handle it? */ /* Yes. We should be strict in handling the format. -Chris */ - sErrorOut = ssprintf("Invalid player options \"%s\"; did you mean '*%d'?", s->c_str(), atoi(*s) ); + sErrorOut = ssprintf("Invalid player options \"%s\"; did you mean '*%d'?", s->c_str(), StringToInt(*s) ); return false; } else diff --git a/src/Profile.cpp b/src/Profile.cpp index 3cf480a415..bfca1207b2 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -1922,7 +1922,7 @@ RString Profile::MakeUniqueFileNameNoExtension( RString sDir, RString sFileNameB continue; ASSERT( matches.size() == 1 ); - iIndex = atoi( matches[0] )+1; + iIndex = StringToInt( matches[0] )+1; break; } diff --git a/src/ProfileManager.cpp b/src/ProfileManager.cpp index 041803238c..812db73a8c 100644 --- a/src/ProfileManager.cpp +++ b/src/ProfileManager.cpp @@ -429,7 +429,7 @@ bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut ) vector vs; GetLocalProfileIDs( vs ); FOREACH_CONST( RString, vs, s ) - iMaxProfileNumber = atoi( *s ); + iMaxProfileNumber = StringToInt( *s ); int iProfileNumber = iMaxProfileNumber + 1; RString sProfileID = ssprintf( "%08d", iProfileNumber ); diff --git a/src/RageBitmapTexture.cpp b/src/RageBitmapTexture.cpp index e6743722c2..aa03982af1 100644 --- a/src/RageBitmapTexture.cpp +++ b/src/RageBitmapTexture.cpp @@ -26,8 +26,8 @@ static void GetResolutionFromFileName( RString sPath, int &iWidth, int &iHeight if( !re.Compare(sPath, asMatches) ) return; - iWidth = atoi( asMatches[0].c_str() ); - iHeight = atoi( asMatches[1].c_str() ); + iWidth = StringToInt( asMatches[0] ); + iHeight = StringToInt( asMatches[1] ); } RageBitmapTexture::RageBitmapTexture( RageTextureID name ) : diff --git a/src/RageTexture.cpp b/src/RageTexture.cpp index f91b07beb6..b049ba159d 100644 --- a/src/RageTexture.cpp +++ b/src/RageTexture.cpp @@ -51,8 +51,8 @@ void RageTexture::GetFrameDimensionsFromFileName( RString sPath, int* piFramesWi *piFramesWide = *piFramesHigh = 1; return; } - *piFramesWide = atoi(asMatch[0]); - *piFramesHigh = atoi(asMatch[1]); + *piFramesWide = StringToInt(asMatch[0]); + *piFramesHigh = StringToInt(asMatch[1]); } const RectF *RageTexture::GetTextureCoordRect( int iFrameNo ) const diff --git a/src/RageUtil.cpp b/src/RageUtil.cpp index 8443b88f7d..4f068df600 100644 --- a/src/RageUtil.cpp +++ b/src/RageUtil.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -193,8 +194,8 @@ float HHMMSSToSeconds( const RString &sHHMMSS ) arrayBits.insert(arrayBits.begin(), "0" ); // pad missing bits float fSeconds = 0; - fSeconds += atoi( arrayBits[0] ) * 60 * 60; - fSeconds += atoi( arrayBits[1] ) * 60; + fSeconds += StringToInt( arrayBits[0] ) * 60 * 60; + fSeconds += StringToInt( arrayBits[1] ) * 60; fSeconds += StringToFloat( arrayBits[2] ); return fSeconds; @@ -1695,6 +1696,20 @@ void MakeLower( wchar_t *p, size_t iLen ) UnicodeUpperLower( p, iLen, g_LowerCase ); } +int StringToInt( const RString &sString ) +{ + int ret; + istringstream ( sString ) >> ret; + return ret; +} + +RString IntToString( const int &iNum ) +{ + stringstream ss; + ss << iNum; + return ss.str(); +} + float StringToFloat( const RString &sString ) { float ret = strtof( sString, NULL ); @@ -2141,7 +2156,7 @@ namespace StringConversion if( sValue.size() == 0 ) return false; - out = (atoi(sValue) != 0); + out = (StringToInt(sValue) != 0); return true; } diff --git a/src/RageUtil.h b/src/RageUtil.h index e9c2149207..17f4d24f0e 100644 --- a/src/RageUtil.h +++ b/src/RageUtil.h @@ -405,6 +405,16 @@ void MakeUpper( char *p, size_t iLen ); void MakeLower( char *p, size_t iLen ); void MakeUpper( wchar_t *p, size_t iLen ); void MakeLower( wchar_t *p, size_t iLen ); +/** + * @brief Have a standard way of converting Strings to integers. + * @param sString the string to convert. + * @return the integer we are after. */ +int StringToInt( const RString &sString ); +/** + * @brief Have a standard way of converting integers to Strings. + * @param iNum the integer to convert. + * @return the string we are after. */ +RString IntToString( const int &iNum ); float StringToFloat( const RString &sString ); bool StringToFloat( const RString &sString, float &fOut ); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 65843ae9f9..617d0140b5 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2617,9 +2617,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if( SM == SM_BackFromDifficultyMeterChange ) { - int i; - std::istringstream ss( ScreenTextEntry::s_sLastAnswer ); - ss >> i; + int i = StringToInt( ScreenTextEntry::s_sLastAnswer ); GAMESTATE->m_pCurSteps[PLAYER_1]->SetMeter(i); SetDirty( true ); } @@ -2646,7 +2644,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) { - int iNum = atoi( ScreenTextEntry::s_sLastAnswer ); + int iNum = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { m_pSong->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_fSongBeat, iNum ); @@ -2655,7 +2653,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if ( SM == SM_BackFromTimeSignatureDenominatorChange ) { - int iDen = atoi( ScreenTextEntry::s_sLastAnswer ); + int iDen = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { m_pSong->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_fSongBeat, iDen ); @@ -2664,7 +2662,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if ( SM == SM_BackFromTickcountChange ) { - int iTick = atoi( ScreenTextEntry::s_sLastAnswer ); + int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { m_pSong->m_Timing.SetTickcountAtBeat( GAMESTATE->m_fSongBeat, iTick ); @@ -2673,7 +2671,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if ( SM == SM_BackFromComboChange ) { - int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); + int iCombo = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { m_pSong->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 814093883a..5ffaa849db 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -2757,7 +2757,7 @@ void ScreenGameplay::SaveReplay() continue; ASSERT( matches.size() == 1 ); - iIndex = atoi( matches[0] )+1; + iIndex = StringToInt( matches[0] )+1; break; } diff --git a/src/ScreenMiniMenu.h b/src/ScreenMiniMenu.h index 365ac90a24..b0ef6176e1 100644 --- a/src/ScreenMiniMenu.h +++ b/src/ScreenMiniMenu.h @@ -4,7 +4,6 @@ #define SCREEN_MINI_MENU_H #include "ScreenOptions.h" -#include #include "GameConstantsAndTypes.h" typedef bool (*MenuRowUpdateEnabled)(); @@ -86,9 +85,7 @@ struct MenuRowDef { for ( int i = low; i <= high; i++ ) { - std::stringstream ss; - ss << i; - choices.push_back(ss.str().c_str()); + choices.push_back(IntToString(i).c_str()); } } diff --git a/src/ScreenPackages.cpp b/src/ScreenPackages.cpp index 7eae34fa03..a9051a3fa1 100644 --- a/src/ScreenPackages.cpp +++ b/src/ScreenPackages.cpp @@ -622,14 +622,14 @@ void ScreenPackages::HTTPUpdate() m_sResponseName = "Malformed response."; return; } - m_iResponseCode = atoi(m_sBUFFER.substr(i+1,j-i).c_str()); + m_iResponseCode = StringToInt(m_sBUFFER.substr(i+1,j-i)); m_sResponseName = m_sBUFFER.substr( j+1, k-j ); i = m_sBUFFER.find("Content-Length:"); j = m_sBUFFER.find("\n", i+1 ); if( i != string::npos ) - m_iTotalBytes = atoi(m_sBUFFER.substr(i+16,j-i).c_str()); + m_iTotalBytes = StringToInt(m_sBUFFER.substr(i+16,j-i)); else m_iTotalBytes = -1; //We don't know, so go until disconnect @@ -696,7 +696,7 @@ bool ScreenPackages::ParseHTTPAddress( const RString &URL, RString &sProto, RStr sServer = asMatches[1]; if( asMatches[3] != "" ) { - iPort = atoi(asMatches[3]); + iPort = StringToInt(asMatches[3]); if( iPort == 0 ) return false; } diff --git a/src/SongOptions.cpp b/src/SongOptions.cpp index fd841b9a3d..de846681b3 100644 --- a/src/SongOptions.cpp +++ b/src/SongOptions.cpp @@ -173,7 +173,7 @@ bool SongOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut ) Regex lives("^([0-9]+) ?(lives|life)$"); if( lives.Compare(sBit, matches) ) { - m_iBatteryLives = atoi( matches[0] ); + m_iBatteryLives = StringToInt( matches[0] ); return true; } diff --git a/src/XmlFile.cpp b/src/XmlFile.cpp index 30e71417b6..7e99ecb41e 100644 --- a/src/XmlFile.cpp +++ b/src/XmlFile.cpp @@ -50,9 +50,9 @@ void XNode::Free() } void XNodeStringValue::GetValue( RString &out ) const { out = m_sValue; } -void XNodeStringValue::GetValue( int &out ) const { out = atoi(m_sValue); } +void XNodeStringValue::GetValue( int &out ) const { out = StringToInt(m_sValue); } void XNodeStringValue::GetValue( float &out ) const { out = StringToFloat(m_sValue); } -void XNodeStringValue::GetValue( bool &out ) const { out = atoi(m_sValue) != 0; } +void XNodeStringValue::GetValue( bool &out ) const { out = StringToInt(m_sValue) != 0; } void XNodeStringValue::GetValue( unsigned &out ) const { out = strtoul(m_sValue,NULL,0); } void XNodeStringValue::PushValue( lua_State *L ) const { From 52f3bdf7a697aa1faa3343a2aedb12782dac96cb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 16:07:35 -0400 Subject: [PATCH 078/333] Remove duplicate metrics. --- Themes/_fallback/metrics.ini | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 13b0757ec4..668d96827b 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -2807,7 +2807,7 @@ Fallback="ScreenOptionsServiceChild" [ScreenSelectGame] Fallback="ScreenOptionsServiceChild" -PrevScreen=Branch.TitleMenu() +PrevScreen="ScreenOptionsService" NextScreen=Branch.TitleMenu() LineNames="1" Line1="conf,Game" @@ -2837,13 +2837,6 @@ Class="ScreenReloadSongs" Fallback="Screen" NextScreen=Branch.TitleMenu() -[ScreenSelectGame] -Fallback="ScreenOptionsServiceChild" -PrevScreen="ScreenOptionsService" -NextScreen=Branch.TitleMenu() -LineNames="1" -Line1="conf,Game" - [ScreenPlayerOptions] Fallback="ScreenOptions" Class="ScreenPlayerOptions" From 750b688de4b40912bbc1d3b5abe8c403db692237 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 16:48:51 -0400 Subject: [PATCH 079/333] Consistent insensitive string comparisons. This seems to reduce the need for a #define, but I need someone on the Windows side to check. --- src/AnnouncerManager.cpp | 4 ++-- src/BGAnimationLayer.cpp | 6 +++--- src/CourseLoaderCRS.cpp | 30 +++++++++++++------------- src/InputMapper.cpp | 2 +- src/LyricsLoader.cpp | 2 +- src/ModIcon.cpp | 2 +- src/NoteSkinManager.cpp | 2 +- src/NotesLoaderDWI.cpp | 36 ++++++++++++++++---------------- src/NotesLoaderJson.cpp | 4 ++-- src/NotesLoaderKSF.cpp | 12 +++++------ src/NotesLoaderSM.cpp | 8 +++---- src/NotesLoaderSMA.cpp | 8 +++---- src/NotesLoaderSSC.cpp | 8 +++---- src/ScreenOptionsMasterPrefs.cpp | 12 +++++------ src/Song.cpp | 6 +++--- src/SongManager.cpp | 2 +- src/global.h | 7 ------- 17 files changed, 72 insertions(+), 79 deletions(-) diff --git a/src/AnnouncerManager.cpp b/src/AnnouncerManager.cpp index ee20dc427e..dd87860a59 100644 --- a/src/AnnouncerManager.cpp +++ b/src/AnnouncerManager.cpp @@ -37,7 +37,7 @@ void AnnouncerManager::GetAnnouncerNames( vector& AddTo ) // strip out the empty announcer folder for( int i=AddTo.size()-1; i>=0; i-- ) - if( !stricmp( AddTo[i], EMPTY_ANNOUNCER_NAME ) ) + if( !AddTo[i].EqualsNoCase( EMPTY_ANNOUNCER_NAME ) ) AddTo.erase(AddTo.begin()+i, AddTo.begin()+i+1 ); } @@ -49,7 +49,7 @@ bool AnnouncerManager::DoesAnnouncerExist( RString sAnnouncerName ) vector asAnnouncerNames; GetAnnouncerNames( asAnnouncerNames ); for( unsigned i=0; i asStyles; diff --git a/src/InputMapper.cpp b/src/InputMapper.cpp index 90e65ae879..6707cf8408 100644 --- a/src/InputMapper.cpp +++ b/src/InputMapper.cpp @@ -948,7 +948,7 @@ MultiPlayer InputMapper::InputDeviceToMultiPlayer( InputDevice id ) GameButton InputScheme::ButtonNameToIndex( const RString &sButtonName ) const { for( GameButton gb=(GameButton) 0; gb asSkinNames; GetAllNoteSkinNamesForGame( GAMESTATE->m_pCurGame, asSkinNames ); for( unsigned i=0; i &Bla } // handle the data - if( 0==stricmp(sValueName,"FILE") ) + if( sValueName.EqualsNoCase("FILE") ) out.m_sMusicFile = sParams[1]; - else if( 0==stricmp(sValueName,"TITLE") ) + else if( sValueName.EqualsNoCase("TITLE") ) { NotesLoader::GetMainAndSubTitlesFromFullTitle( sParams[1], out.m_sMainTitle, out.m_sSubTitle ); @@ -460,22 +460,22 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla ConvertString( out.m_sSubTitle, "utf-8,english" ); } - else if( 0==stricmp(sValueName,"ARTIST") ) + else if( sValueName.EqualsNoCase("ARTIST") ) { out.m_sArtist = sParams[1]; ConvertString( out.m_sArtist, "utf-8,english" ); } - else if( 0==stricmp(sValueName,"GENRE") ) + else if( sValueName.EqualsNoCase("GENRE") ) { out.m_sGenre = sParams[1]; ConvertString( out.m_sGenre, "utf-8,english" ); } - else if( 0==stricmp(sValueName,"CDTITLE") ) + else if( sValueName.EqualsNoCase("CDTITLE") ) out.m_sCDTitleFile = sParams[1]; - else if( 0==stricmp(sValueName,"BPM") ) + else if( sValueName.EqualsNoCase("BPM") ) { const float fBPM = StringToFloat( sParams[1] ); @@ -491,7 +491,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla NoteRowToBeat(0), fBPM ); } } - else if( 0==stricmp(sValueName,"DISPLAYBPM") ) + else if( sValueName.EqualsNoCase("DISPLAYBPM") ) { // #DISPLAYBPM:[xxx..xxx]|[xxx]|[*]; int iMin, iMax; @@ -515,17 +515,17 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla } } - else if( 0==stricmp(sValueName,"GAP") ) + else if( sValueName.EqualsNoCase("GAP") ) // the units of GAP is 1/1000 second out.m_Timing.m_fBeat0OffsetInSeconds = -StringToInt( sParams[1] ) / 1000.0f; - else if( 0==stricmp(sValueName,"SAMPLESTART") ) + else if( sValueName.EqualsNoCase("SAMPLESTART") ) out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]); - else if( 0==stricmp(sValueName,"SAMPLELENGTH") ) + else if( sValueName.EqualsNoCase("SAMPLELENGTH") ) out.m_fMusicSampleLengthSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]); - else if( 0==stricmp(sValueName,"FREEZE") ) + else if( sValueName.EqualsNoCase("FREEZE") ) { vector arrayFreezeExpressions; split( sParams[1], ",", arrayFreezeExpressions ); @@ -547,7 +547,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla } } - else if( 0==stricmp(sValueName,"CHANGEBPM") || 0==stricmp(sValueName,"BPMCHANGE") ) + else if( sValueName.EqualsNoCase("CHANGEBPM") || sValueName.EqualsNoCase("BPMCHANGE") ) { vector arrayBPMChangeExpressions; split( sParams[1], ",", arrayBPMChangeExpressions ); @@ -577,10 +577,10 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla } } - else if( 0==stricmp(sValueName,"SINGLE") || - 0==stricmp(sValueName,"DOUBLE") || - 0==stricmp(sValueName,"COUPLE") || - 0==stricmp(sValueName,"SOLO") ) + else if( sValueName.EqualsNoCase("SINGLE") || + sValueName.EqualsNoCase("DOUBLE") || + sValueName.EqualsNoCase("COUPLE") || + sValueName.EqualsNoCase("SOLO") ) { Steps* pNewNotes = new Steps; LoadFromDWITokens( @@ -597,8 +597,8 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla else delete pNewNotes; } - else if( 0==stricmp(sValueName,"DISPLAYTITLE") || - 0==stricmp(sValueName,"DISPLAYARTIST") ) + else if( sValueName.EqualsNoCase("DISPLAYTITLE") || + sValueName.EqualsNoCase("DISPLAYARTIST") ) { /* We don't want to support these tags. However, we don't want * to pick up images used here as song images (eg. banners). */ diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp index ba7e6647f1..0d44550d97 100644 --- a/src/NotesLoaderJson.cpp +++ b/src/NotesLoaderJson.cpp @@ -143,9 +143,9 @@ static void Deserialize( Song &out, const Json::Value &root ) out.m_fMusicSampleStartSeconds = (float)root["SampleStart"].asDouble(); out.m_fMusicSampleLengthSeconds = (float)root["SampleLength"].asDouble(); RString sSelectable = root["Selectable"].asString(); - if( !stricmp(sSelectable,"YES") ) + if( sSelectable.EqualsNoCase("YES") ) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if(!stricmp(sSelectable,"NO")) + else if( sSelectable.EqualsNoCase("NO") ) out.m_SelectionDisplay = out.SHOW_NEVER; out.m_fFirstBeat = (float)root["FirstBeat"].asDouble(); diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 4cfaaf0001..a5530b3359 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -286,12 +286,12 @@ static void LoadTags( const RString &str, Song &out ) split( str, " - ", asBits, false ); // Ignore the difficulty, since we get that elsewhere. if( asBits.size() == 3 && ( - !stricmp(asBits[2], "double") || - !stricmp(asBits[2], "easy") || - !stricmp(asBits[2], "normal") || - !stricmp(asBits[2], "hard") || - !stricmp(asBits[2], "crazy") || - !stricmp(asBits[2], "nightmare")) + asBits[2].EqualsNoCase("double") || + asBits[2].EqualsNoCase("easy") || + asBits[2].EqualsNoCase("normal") || + asBits[2].EqualsNoCase("hard") || + asBits[2].EqualsNoCase("crazy") || + asBits[2].EqualsNoCase("nightmare")) ) { asBits.erase( asBits.begin()+2, asBits.begin()+3 ); diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 4a2bf428f7..b8099a1e01 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -596,18 +596,18 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else if( sValueName=="SELECTABLE" ) { - if(!stricmp(sParams[1],"YES")) + if(sParams[1].EqualsNoCase("YES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if(!stricmp(sParams[1],"NO")) + else if(sParams[1].EqualsNoCase("NO")) out.m_SelectionDisplay = out.SHOW_NEVER; // ROULETTE from 3.9. It was removed since UnlockManager can serve // the same purpose somehow. This, of course, assumes you're using // unlocks. -aj - else if(!stricmp(sParams[1],"ROULETTE")) + else if(sParams[1].EqualsNoCase("ROULETTE")) out.m_SelectionDisplay = out.SHOW_ALWAYS; /* The following two cases are just fixes to make sure simfiles that * used 3.9+ features are not excluded here */ - else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) + else if(sParams[1].EqualsNoCase("ES") || sParams[1].EqualsNoCase("OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 824a526e41..dbb0089494 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -244,18 +244,18 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else if( sValueName=="SELECTABLE" ) { - if(!stricmp(sParams[1],"YES")) + if(sParams[1].EqualsNoCase("YES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if(!stricmp(sParams[1],"NO")) + else if(sParams[1].EqualsNoCase("NO")) out.m_SelectionDisplay = out.SHOW_NEVER; // ROULETTE from 3.9. It was removed since UnlockManager can serve // the same purpose somehow. This, of course, assumes you're using // unlocks. -aj - else if(!stricmp(sParams[1],"ROULETTE")) + else if(sParams[1].EqualsNoCase("ROULETTE")) out.m_SelectionDisplay = out.SHOW_ALWAYS; /* The following two cases are just fixes to make sure simfiles that * used 3.9+ features are not excluded here */ - else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) + else if(sParams[1].EqualsNoCase("ES") || sParams[1].EqualsNoCase("OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 3ae4b3a0d4..4e511c844a 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -276,16 +276,16 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="SELECTABLE" ) { - if(!stricmp(sParams[1],"YES")) + if(sParams[1].EqualsNoCase("YES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; - else if(!stricmp(sParams[1],"NO")) + else if(sParams[1].EqualsNoCase("NO")) out.m_SelectionDisplay = out.SHOW_NEVER; // ROULETTE from 3.9 is no longer in use. - else if(!stricmp(sParams[1],"ROULETTE")) + else if(sParams[1].EqualsNoCase("ROULETTE")) out.m_SelectionDisplay = out.SHOW_ALWAYS; /* The following two cases are just fixes to make sure simfiles that * used 3.9+ features are not excluded here */ - else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES")) + else if(sParams[1].EqualsNoCase("ES") || sParams[1].EqualsNoCase("OMES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; else if( StringToInt(sParams[1]) > 0 ) out.m_SelectionDisplay = out.SHOW_ALWAYS; diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 347ecf041d..6ef345ceaf 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -181,7 +181,7 @@ static void GameSel( int &sel, bool ToSel, const ConfOption *pConfOption ) sel = 0; for(unsigned i = 0; i < choices.size(); ++i) - if( !stricmp(choices[i], sCurGameName) ) + if( !choices[i].EqualsNoCase(sCurGameName) ) sel = i; } else { vector aGames; @@ -222,12 +222,12 @@ static void Language( int &sel, bool ToSel, const ConfOption *pConfOption ) { sel = -1; for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) - if( !stricmp(vs[i], THEME->GetCurLanguage()) ) + if( !vs[i].EqualsNoCase(THEME->GetCurLanguage()) ) sel = i; // If the current language doesn't exist, we'll show BASE_LANGUAGE, so select that. for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) - if( !stricmp(vs[i], SpecialFiles::BASE_LANGUAGE) ) + if( !vs[i].EqualsNoCase(SpecialFiles::BASE_LANGUAGE) ) sel = i; if( sel == -1 ) @@ -276,7 +276,7 @@ static void RequestedTheme( int &sel, bool ToSel, const ConfOption *pConfOption { sel = 0; for( unsigned i=1; im_sTheme.Get()) ) + if( !vsThemeNames[i].EqualsNoCase(PREFSMAN->m_sTheme.Get()) ) sel = i; } else @@ -302,7 +302,7 @@ static void Announcer( int &sel, bool ToSel, const ConfOption *pConfOption ) { sel = 0; for( unsigned i=1; iGetCurAnnouncerName()) ) + if( !choices[i].EqualsNoCase(ANNOUNCER->GetCurAnnouncerName()) ) sel = i; } else @@ -329,7 +329,7 @@ static void DefaultNoteSkin( int &sel, bool ToSel, const ConfOption *pConfOption po.FromString( PREFSMAN->m_sDefaultModifiers ); sel = 0; for( unsigned i=0; i < choices.size(); i++ ) - if( !stricmp(choices[i], po.m_sNoteSkin) ) + if( !choices[i].EqualsNoCase(po.m_sNoteSkin) ) sel = i; } else diff --git a/src/Song.cpp b/src/Song.cpp index 5743eb9199..2bc3df3d64 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -611,13 +611,13 @@ void Song::TidyUpData() // Skip any image that we've already classified - if( HasBanner() && stricmp(m_sBannerFile, arrayImages[i])==0 ) + if( HasBanner() && m_sBannerFile.EqualsNoCase(arrayImages[i]) ) continue; // skip - if( HasBackground() && stricmp(m_sBackgroundFile, arrayImages[i])==0 ) + if( HasBackground() && m_sBackgroundFile.EqualsNoCase(arrayImages[i]) ) continue; // skip - if( HasCDTitle() && stricmp(m_sCDTitleFile, arrayImages[i])==0 ) + if( HasCDTitle() && m_sCDTitleFile.EqualsNoCase(arrayImages[i]) ) continue; // skip // todo: add checks for Jacket, Disc, and CDImage -aj diff --git a/src/SongManager.cpp b/src/SongManager.cpp index fe4bb51cd2..e91b1c4d41 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -879,7 +879,7 @@ void SongManager::InitRandomAttacks() continue; } - if( stricmp(sType,"ATTACK") != 0 ) + if( !sType.EqualsNoCase("ATTACK") ) { LOG->Warn( "Got \"%s:%s\" tag with wrong declaration", sType.c_str(), sAttack.c_str() ); continue; diff --git a/src/global.h b/src/global.h index 19a6d3c76b..b90f6c86c7 100644 --- a/src/global.h +++ b/src/global.h @@ -192,13 +192,6 @@ typedef StdString::CStdString RString; #include "RageException.h" -#if !defined(WIN32) -/** @brief Define stricmp to be strcasecmp. */ -#define stricmp strcasecmp -/** @brief Define strnicmp to be strncasecmp. */ -#define strnicmp strncasecmp -#endif - /* Define a few functions if necessary */ #include From 90469f0f254ca497a1c23f394a34b5acabd4f552 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Wed, 11 May 2011 16:08:29 -0500 Subject: [PATCH 080/333] .c_str() --- src/BPMDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BPMDisplay.cpp b/src/BPMDisplay.cpp index 981976974f..f4b27d51b2 100644 --- a/src/BPMDisplay.cpp +++ b/src/BPMDisplay.cpp @@ -205,7 +205,7 @@ void BPMDisplay::SetBpmFromCourse( const Course* pCourse ) StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; Trail *pTrail = pCourse->GetTrail( st ); // GetTranslitFullTitle because "Crashinfo.txt is garbled because of the ANSI output as usual." -f - ASSERT_M( pTrail, ssprintf("Course '%s' has no trail for StepsType '%s'", pCourse->GetTranslitFullTitle(), StringConversion::ToString(st).c_str() ) ); + ASSERT_M( pTrail, ssprintf("Course '%s' has no trail for StepsType '%s'", pCourse->GetTranslitFullTitle().c_str(), StringConversion::ToString(st).c_str() ) ); m_fCycleTime = 0.2f; From 04d45bca1c50b44bee8a802187b1bdcbaa11b9ca Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 17:13:22 -0400 Subject: [PATCH 081/333] [splittiming] Right, we store ints. --- src/NotesLoaderKSF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index af36be25d2..ca066c3361 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -194,7 +194,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, RString temp = sRowString.substr(2,sRowString.size()-3); newTick = StringToInt(temp); bTickChangeNeeded = true; - out.m_Timing.AddTickcountSegment(TickcountSegment(fCurBeat, newTick)); + out.m_Timing.AddTickcountSegment(TickcountSegment(BeatToNoteRow(fCurBeat), newTick)); continue; } else From da8017f91e1f1ac44fb4263c4b95cb25e34e8d4d Mon Sep 17 00:00:00 2001 From: Jonathan Payne Date: Wed, 11 May 2011 14:34:02 -0700 Subject: [PATCH 082/333] coming close to a point where working on this will be a breeze IMO. --- .../ScreenSelectMusic decorations.lua | 7 +-- ...=> ScreenWithMenuElements decorations.lua} | 9 +++ .../default.lua | 14 +++++ .../ScreenWithMenuElements underlay/grid.png | Bin 0 -> 2838 bytes Themes/themekit/Graphics/Banner all music.png | Bin 0 -> 4910 bytes Themes/themekit/Graphics/Banner mode.png | Bin 0 -> 3634 bytes Themes/themekit/Graphics/Banner random.png | Bin 0 -> 5027 bytes Themes/themekit/Graphics/Banner roulette.png | Bin 0 -> 4133 bytes .../Graphics/Common fallback background.png | Bin 0 -> 418034 bytes .../Graphics/Common fallback banner.png | Bin 0 -> 713 bytes .../MusicWheelItem Song ColorPart.lua | 14 ----- .../MusicWheelItem Song NormalPart.lua | 6 -- .../ScreenWithMenuElements HelpDisplay.lua | 3 + Themes/themekit/Languages/en.ini | 56 ++++++++++++++++++ Themes/themekit/metrics.ini | 41 +++++++++---- 15 files changed, 115 insertions(+), 35 deletions(-) rename Themes/themekit/BGAnimations/{ScreenWithMenuElements decorations - Copy.lua => ScreenWithMenuElements decorations.lua} (74%) create mode 100644 Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua create mode 100644 Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/grid.png create mode 100644 Themes/themekit/Graphics/Banner all music.png create mode 100644 Themes/themekit/Graphics/Banner mode.png create mode 100644 Themes/themekit/Graphics/Banner random.png create mode 100644 Themes/themekit/Graphics/Banner roulette.png create mode 100644 Themes/themekit/Graphics/Common fallback background.png create mode 100644 Themes/themekit/Graphics/Common fallback banner.png delete mode 100644 Themes/themekit/Graphics/MusicWheelItem Song ColorPart.lua delete mode 100644 Themes/themekit/Graphics/MusicWheelItem Song NormalPart.lua create mode 100644 Themes/themekit/Graphics/ScreenWithMenuElements HelpDisplay.lua create mode 100644 Themes/themekit/Languages/en.ini diff --git a/Themes/themekit/BGAnimations/ScreenSelectMusic decorations.lua b/Themes/themekit/BGAnimations/ScreenSelectMusic decorations.lua index f5a37674cd..b76210c621 100644 --- a/Themes/themekit/BGAnimations/ScreenSelectMusic decorations.lua +++ b/Themes/themekit/BGAnimations/ScreenSelectMusic decorations.lua @@ -3,7 +3,7 @@ -- these elements. local t = LoadFallbackB(); --- Legacy StepMania 4 Function +-- local function CreateStepDisplay(pn) local function set(self, player) self:SetFromGameState( player ); @@ -23,9 +23,7 @@ local function CreateStepDisplay(pn) return t; end - - - +-- Create StepsDisplay for each Player. for pn in ivalues(PlayerNumber) do local MetricsName = "StepsDisplay" .. PlayerNumberToString(pn); t[#t+1] = CreateStepDisplay(pn) .. { @@ -44,4 +42,5 @@ for pn in ivalues(PlayerNumber) do end; }; end + return t \ No newline at end of file diff --git a/Themes/themekit/BGAnimations/ScreenWithMenuElements decorations - Copy.lua b/Themes/themekit/BGAnimations/ScreenWithMenuElements decorations.lua similarity index 74% rename from Themes/themekit/BGAnimations/ScreenWithMenuElements decorations - Copy.lua rename to Themes/themekit/BGAnimations/ScreenWithMenuElements decorations.lua index 0a6c72ce04..02dddd67f5 100644 --- a/Themes/themekit/BGAnimations/ScreenWithMenuElements decorations - Copy.lua +++ b/Themes/themekit/BGAnimations/ScreenWithMenuElements decorations.lua @@ -24,4 +24,13 @@ t[#t+1] = StandardDecorationFromFileOptional("TextHeader","TextHeader") .. { }; -- Image displayed on the bottom of the screen t[#t+1] = StandardDecorationFromFileOptional("Footer","Footer"); +t[#t+1] = StandardDecorationFromFileOptional( "HelpDisplay", "HelpDisplay" ) .. { + InitCommand=function(self) + local s = THEME:GetString(Var "LoadingScreen","HelpText"); + self:SetTipsColonSeparated(s); + end; + SetHelpTextCommand=function(self, params) + self:SetTipsColonSeparated( params.Text ); + end; +}; return t \ No newline at end of file diff --git a/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua b/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua new file mode 100644 index 0000000000..72fd7fce4a --- /dev/null +++ b/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua @@ -0,0 +1,14 @@ +local t = Def.ActorFrame { + InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y); +}; +-- +t[#t+1] = LoadActor("grid") .. { + InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/16,SCREEN_HEIGHT/16); + OnCommand=cmd(diffuse,color("0,0,0,0.125")); +}; +t[#t+1] = LoadActor("grid") .. { + InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/32,SCREEN_HEIGHT/32); + OnCommand=cmd(diffuse,color("0,0,0,0.25")); +}; +-- +return t \ No newline at end of file diff --git a/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/grid.png b/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3c6ad15db7f986b9a9f4b9708ebed851845b71 GIT binary patch literal 2838 zcmV+x3+eQUP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000%NklF*p2K#&LL#eNSgs(R=NtlM@?y|zLGN9JK3ZDl3 zeZ%S<8Zcm*xL2m~xGC{Gwqy@_%2gW%_BSp3ON>xs1_q}zFt`}sfGLm`|5}aqwkZIV z79QH#|9D3EdjBhL54`y)iMNnQtj-c#_t5wEWVfy*wYKl2H;NygCh=Ahag_dHNg6kI znLhtL{p%Hf{m+#plO)=R9rb^oiW+BrkV_>TrGMYwzf_)>VGLmZbenT#|DS$|0cmc> znuCA-FsZeXE7vyv@I?|!;C7i2fo89oyJKyprz5j&W%l;Ul6-=LB1SE0e zF8hZkY1}+7vo>|B^$33ec{Xe6-zt3bYy4WlxAZhjgLuGUGRWQ~b^`Otr`&08+)x#N}zT#B0x7wQtI2MExx!W>pRLQG5QoA4x!8+Eg{t*Lt_ z)so;(T0)k3pe!}@FMJFJFYaVp%s{PCI7G(ms2&Jq)^`Pmy3Q7YcC3HzP96PvEB^0q zVNyOj&f>bLhV(J52xHGgsaxH8;K@v8eJA-6ZSdn0VtmV%kw!BMq^keBd)dCrN1o~J z;n(8A^SBHsdKQ$Ws!fd=n25kiSdtJH;1(cAcXc4Ql;DRLLjCXAc~j}8k})5`kO2X1 zly(odLKgsxfCKWGa_n?xu;=I{j<$4rTvI4G&frJKYj!ma8w+f}H#m4C#-aB9bhjLOc8?~>xF{GO%!S}B8He$~dc*j*w1|Tv)ZgBw3*=Sv_iPU6B!PQu zh!skCMncblKwuYq#^X#`MwGNeXp+VaJ#~fyU1$a9k!J&WM)jZRWt~M&K!y)t*SG+1 zA0riu2w2Mw*9C_b<52oPDFuRPOq>KULD;q{x1Ro&S4zh}ucc*-fnS%AtA}?%C@lOR zlt74H+BLBmuiZ5uh(Gwu{jd;a@cjq>XYk|WmAS=Q!iP&fg|N6XJCE*VRE*FR0KH)> zBmXN`zg@-`uzC3H2X@DVae4TmM^S9wG0f%RhgcsaFd+UjF}`Zn z0qVmj+q=>qN)8U45D5ogLxTWWMNcGEB<<#IU0JfnU`ua-weTd3Yj&J%2|k5XxNTS= zDm=2?7ZeU>cLZT{jziqSza9htE&jXcw+R2o4sHwha-F&)<3dbz6`)WC%csj%W~Hr@ zOj4g*c}iFhnv`3N_x!^3-~Gk@SKloTjaC*Z zguGlOYeGx30BM4mM;lzD>}@>(x9Y7U<+E3CsALDP(AD2P{kx_GkVd@S$?e+chhu5@ ztav=E$vD`+{(({er4TRbJ^&9E6;%|Lq_O(n)TMyW7XcF#2BA`2sKQFnynTe2hOhvV z0RuoL7@$;#bxp4aBVavR#c(#xyzpr8gVTxtK3Tt)Ms4pb|!f2LcZXv?J`p`%WPaNj5RgnDkwoOTz95X zm#d2nMbfx=JOd+rkIMWacnkhIE1|4X+vYIEDHoXT>`;8LTIR$85?+N>Mbt^CIZ%qB zf@aE?AekTlPU&o=`0nrX5AM_pzz60+u ztPZG2!-QB+>BQ2zX&+)v!r2%l0Knvo$g(4b0D_8^mB-*Xhk89*@*rYm{5bJ_uYL^Q z>oS0|Z0H{P+o$&a^cUqT(LTxjtZ0%O^!T0?#T} zH42ebk@mW$T~mPu(@9aiq!o&!u>h=YQ^&FF%A%{(F0wo1*$3!T8a~G&RI45j9N!cS ziwbMRna-XEh*ZY$m-Fzi6Nihz;fd0ZUdrEhd*NHV0rWu*+w=ErA9(9H_Qd2VRsF-s znot?0UiuZYm_}$^HM2md8o#~{%7p&!&iuo3N-rf0C{NrVl+;QA9^@s|rzO*c7SUUH zlKPFh%4tnRc2srS(p{y>q<_y?Tg<*i#O(YfH`8|nZ zy(yJYfh()L?lM47D`3e}5;6km#cnze0aIomv50V-#K^+z-WPs3^f!N;?v!Q_<-v2w z@*Gwh_Zujk!WRZrg(U`|A~8pD-v&tWmdOqLS=|U5QbI0Fs0;Y^ACLu-6wpz zjfM#WnrTqag`)xCNMvG>iW-wgF)yJfG;NtKR9Xm<2Bqti?ng1-BT_nbk!6_#J_70= zvs=k@mtul0iyWvpX-r0@X0U1|(>1F~XF%)??)!1|QMh-bvXJ6CpECa{M$CvffIvMM zR+jeQIua*wJX8|Y@e^V{sh4sr^;T_NFi!d6H4xk1)wy) zt4Dc$@Wvg&DA*1@_nlluz97a7Hx;!oLb99Gqy%Ib!O-((N!&n2lKZKlN$Q8iRM(Ue zD0+WX|3j!Coj81O;d(9w6PG481?90RDF950KxbE~OQgEY2hViIpm?I7A2YD=Bu-(P zh23k@t&!qKpOq)3MXAd)#m?WgPP}s`nLjUbP==u%5}6YfXf}d1cw)SNZjt$KQY9Vw zt0(vW=ZD237eFl0`;s=wOGT~9;xddJ+?J*QxYfe_oBdxvy=LU<3~rwt@x^%_*xY~s zbhXRVHHbov66s4omP15rmaRhYz0;r_GpoD9kvK^bb+lJ-Tm}^BC07=fSvg5f?@0Ck z-Z8uz!-HZOe0et2l7Mn-zAvr76i?mR=;b4~ zghF-!vYGkaX)q=rPB0)70E54_3na?s;|@eIqE+s~>%zP~&Hq-GOn5W9|2us_v+NxB zlZOl0>C)*-BbE7DDI*0bT41d2C$B@180!pXq?rX0u+HyVtt6Y-^NW&1D{ht*k?#RV z94+mDs+#))sThZ>1WNxOJy3Vf(#Z=0ZwwJ<84|DINQi-q*=DeK$F;abFjtej8d^GY z8S1|3>ae(xATd~-tsKO_I;%X0ijq+LWUTPW4ggkw&nNC7w`lwSL}jIu=UH0G;Q=~a4;&s%r&{v&->!ydE8Ft=yR5KF3$wVc zSW9gWn-;*u>}MeN|J%<%QHk>;$#$tktIL%osuV8?rD$pmHJ_t5rDlm~KGO!x6pjQO z59%qWud^FFf?+hONtt^wO-=nDM@fz)QOiN=ti65&?n)VGl)f3w$1$GM8M}Zjgf2fbq5i@N3eNSqxqzk<->w*4o6~IT6V}&N?=fD zB^I{;wiff@>V)?nPhy9qMXeAq4IQ|X&0QeqJa~F)?+d>=_?M6R?SP)3-2d9)(#bJI zaIzgfCC}1b?8Ld%#S70(cO(?cCIvuhB@4MV%;N9H;Z-sSD&W^;U>0~Te#zlX;&fw^ zB;JDL#vg1O0?lo+rPI@!y9d44Nk1YSaW()ZynA zLy$Oe)dJWyVvbT49#Fn0p($@(4+^AoFrXOr&ka`dN%5f^#h| z@MwfXSwP>8h?f{e>|sj6C=eo(2<7TBLnnMZsctxJ)M3%>O@4;_f$+71 zu)%8qZsdFsW?AGD$!98;q|H_^N%J#c0l)%)1ponn0Kg3Z761eQ zo6~1?7b{@Na zP2#+qCU(|&G)W({V`xRwlEM}c6_oy10|NCAlKl^mDzH`f146QQjpRCutk!(X5@sjvu>oIp^Nl-q|~wuKRbhN267wd+uZ8@0|0U zbI*h^Qko~F5@9|G3)P6O6Fo*Kjp!HQsjaUHBfgIh6Ayz2XKCWm`9yl%L;6KNm*F~M zt`JK3Q)3Y+%*Vrv_pK$krfv|e{^3E%V}BzzrWEH`=0_wVi+=hQY>)cO^!V|lBW5<>D9Ch`|2vqwK1IdC#R zF^dxsZCYfyKd@z;x1!B;OgAp(O39r%2aDuRU*L<(5Q8tG>($MGv4JgXhrZ>J+JeXH z{?*gOjuWQ|47=V9;FsHPO#h!+)i&Dy_2|F@nP;*m#!2&HVkZct5{qB%9(u4Rs!t#J z4PZspCk%XTUr*P-*3HSqE#&$#{Ko#lf4*BNYQ(e=#FSQ;=+Fb&~C^8P)e=qs5;^{#e=^()$l=OzprPF zAU{#Iz@abbvM!+JEo&P6@%>W2mbeLf^k?br$DS(8Od*>WREqgt$0G81WZ;{3!KVG& zcjNg@2M-n!$)IXeph;v?hRI(_YgB>iGy<$@uR4-k(#CU5f)AmA``>zt7%fcA0A52_ zDexp1fx?x+_nTGGKm7W>+{v?`pIqX4YgY7ay;HG)p@+BhKld6jETG+pU7sZvB`SE% zp_7@Hc9-=XuL~D}iIwr>3jp8DYlqMpO}h+Vmg-)noM&+RtK>QY=fvq~)p}jRqd|d~ z*U=WnXm0E*;7R61qGp05f};EPx`eXOOl@8hqCgYE00Op9Ds6kn6UyPmd!KkAe-UDZ zj%pu_lii1g-#9S(==a0$?b~`sX6JkPscXctc`nPmo7xov0ItvX(vhjZp9lSIk9;Hj z#f?fF$n4xhj2OCbLl@SbY>TV5wBsE@Mfs>&W@tIYwCa=sH4MP_Q)`!oX-sZxTp9q! zJw6~D(~!u9(#?}$11L<-lq-fBg4pX!t?y9K-}CFI5o(qrGgQWM7pD848QtFh?XYs% zTc3G#KPk>*Ccu~yqjIOl5!QABmcj*nzfhd({qxSfOI@#Xc{rH#ZP`5h?gzwn69ERU@t#7zeeuL#xf0GLQ(}!i)KU@{uF3?__dGYiR2(+`2diOC{Yn z?5i4pZlD1;O+4S=_Y$+ygD<{4`jdylnrIKZ50m*ho(UMB=-srq(k#b=Qzcr_NTLRS z53N^hGz`EO8L$KvRV_qRfe_PQkpyF8&(YMTt_mcbKFcG34v0x_T&h%BGB3YfxHgBb zG|_?v5Uz3}?ELJp5Bov}0OsV^;Td9lwHrtpRUj5k0M2<`%ZU_<4+`zObG5*a8@0Ze>SB7q^{!26}B7g*? zMgfi@XHDO>x+2j$GFG@Yi$2>%IdD#5}d<)m+RrvVDzAq&u``>#kfAO-C z0A!DxA~a}&b8QvkXjD2FfO-8sISLIzip_}THrI(M=>)X>h?YBUZ>j-^Zj0zTTvKNJ zH6?fQLoz>uWhjd^44_UEfE6vA5K99PbxhT#`hMTt8^RqsfIlzUp&*#k63n9{&5-7C zTD12_(xM7nbv3KiNkq9W-M`GX&tcKVFro$^twmW!D6`LF0H@B24v6}_0caS&@)jil z0Q47TOG+{dd8Dutp_4s&S}+-PE>dtqI9j3#Mg5rSvt@HmnOofPkjb=82hlrHt%54*J4kQ=O{& zr+vRCRfSSM%MueCRiL^QmRh?k%u>+)4aADlnFE)ypOWw4T?dJ20sbH+sCcy;QJO5w z6iFbmnv^?tRRo4=5dfQ|Nk~LJU2{5nbU zY~kZYVLo4&Dv!uTa_0^L&_!Fd(u*;0S7&k&wkIeX;bC;u0CH!}bJSKQ0F1c?+xDQ^ zq@8(X555#0*dmlDT|l|h=W!P+PMTWL*((wdr@BN%qYTPes>@YNE1J&p)L8cT$Dg+G z^xb=F*!?3Ytpp?nk$h1T6bOE^W0$~B%MigA8Gid{VQ!XKB|$Teh_pDV;GLriM z!Drgs%%b_U6O@1m4bZQ%(I51H6)Bq8BWEy-SP7z=yrm)$ePuKcn}2(7BT0h-K?dBa z0t*cwQmK?)c`x^u4m=9f0PaEgNY}(7BL~L9g`;G9>(F=Z9^A37aP2Da3e*(Tf8Anm z+pc3)7U186QY@;O4rD2+&!%D{U0lz>lV0CG^wkZ~BlSP~Dr%Z=;5h!nFQ(Qlk46AI zu#Y_#YSvC^9jCty3RHq`bHh+5%*^v^S~cgB?tk|o9L2Uu)9YxhhRc{J8iHD8*YWgi zT@^uK%Po*MkL(|V_yBN(+D>}Y%IKG9!*3oOdH)1~_Qu-@HTV~1=7#s35ieVJrIAJz2tQL4UR)wr zcy96c&Yn0Q-1|y0okImPj%-0UTssyX#fqUOZl(;LNt^lUnZcL#ZcE?8$7LKC_}c9Q zL`oF>{m;LS7sl}x5^u${wZm1uk#6#w$5Awg9+t;b z1U^kBQ57`Wk%n}UE<9o(TW?*&nY3Ireu$v>3{yU{3ln4X`u-@uwe0&YIS-I+%N#&=OkWo1_YlS=Y5(6xV_xj$?zz;f5Q~jbetB-5^? zyN(TWNu|Kt!nGOr6^n2hW&reYUt6@DO8PF_;A)8siB`N`uYnt7P}=ikmRy~{(ue4P zM*@R)tK998?CDAR^S_XpX~KLl%E?chXtCfc$$@9d^kp0sLdzv{68dhC>Imf~7&1nV zT^u?15tx?v&*VgqDOXN4r0J#|@GGO-EY1A<<+ zH}Q*JollQpiH2e%k#|OTX{zLlA`aM~kE3%l!0AbGURa&%=MkS`#Vnjo!+e9^xHY>t zgyqg6@l^wm|7oFN;vxvy>OPyFAwdYk1Jn}vMlt1$>Rc%K<2yG<7c@euSj1n#qzmW0 zoI(MBBD{6&(Llin0!US14EMsvFK>#TyG*i!%;B?U5f=PPK?4X!5@mPwl}jb@fhDOS z>KpyP9eXhW0EB@kc7pqVbgI&&TtjHG!{e-z0yveaVC8oH0d4^B3j`Jb1ONg60e~YI zEC2`q1ORRTumB(c5CFIVzyg2(z!L~800;m)fxrU51NdY#6riRhZ2$lO07*qoM6N<$ Ef|Ul<&;S4c literal 0 HcmV?d00001 diff --git a/Themes/themekit/Graphics/Banner random.png b/Themes/themekit/Graphics/Banner random.png new file mode 100644 index 0000000000000000000000000000000000000000..2a19b14c37610bd2ecee68025169ef30b4051e83 GIT binary patch literal 5027 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 j69_B-2mm~RzyiPnR^Vr)_b>En|bLJd4Z~!*x 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�+z~WS)W=96&2 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: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

*AbrCjk-i!grAn2c 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�%8&nUOz;tB^wT;dp`x76+GQd&um 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 lG*DJ*X@wG@UCTSGEyv^FOfNf8xb37Td=CzA6) zR1i6=A}zI+Y0HA31hp(XM+ZxAZFN&?>n67Pwl@A3b@P4S_WPdq_wF%>g#6;7l|=xG z1>1OaKpuHQL@OZYy`N`*Rk@yEJRG4vNl(_YLdA&k<=FC1B^mRR`z?QP+|+I zjLdb3>F=2+hy17Ms~bG2s!`5FatC{>*_F=tn3WZzQ3)g2x%1cf1{yyTW|k*rl&Z~a zMKuAjRYqDQRW-yB{|lByQjstPYD?M~Kpb=~U!9%3Vr^XXR&Jc@`jK9r8?}ZcLR5ls zu!tk@Kd^};d=#iHVG>6S^wsktKTD-n$)eo5{PR?+a!bx3B#B-sK{>?4;ikafb)zg= zT&&J|1{vH;8GE*y AcmMzZ literal 0 HcmV?d00001 diff --git a/Themes/themekit/Graphics/MusicWheelItem Song ColorPart.lua b/Themes/themekit/Graphics/MusicWheelItem Song ColorPart.lua deleted file mode 100644 index d3d0df30f3..0000000000 --- a/Themes/themekit/Graphics/MusicWheelItem Song ColorPart.lua +++ /dev/null @@ -1,14 +0,0 @@ -return Def.ActorFrame { - Def.Quad { - InitCommand=cmd(x,-128+4;zoomto,4,46); --- OnCommand=cmd(diffuse,color("0,0,0,0.5")); - }; ---[[ Def.Quad { - InitCommand=cmd(x,-128+16+6;zoomto,32,46); --- OnCommand=cmd(faderight,1;diffusealpha,0.5); - }; --]] ---[[ Def.Quad { - InitCommand=cmd(x,2;y,23;zoomto,320,1); --- OnCommand=cmd(diffuse,color("0,0,0,0.5")); - }; --]] -}; \ No newline at end of file diff --git a/Themes/themekit/Graphics/MusicWheelItem Song NormalPart.lua b/Themes/themekit/Graphics/MusicWheelItem Song NormalPart.lua deleted file mode 100644 index 7c5b876099..0000000000 --- a/Themes/themekit/Graphics/MusicWheelItem Song NormalPart.lua +++ /dev/null @@ -1,6 +0,0 @@ -return Def.ActorFrame { - Def.Quad { - InitCommand=cmd(x,4;zoomto,256-4,46); - OnCommand=cmd(diffuse,color("0,0,0,0.5")); - }; -}; \ No newline at end of file diff --git a/Themes/themekit/Graphics/ScreenWithMenuElements HelpDisplay.lua b/Themes/themekit/Graphics/ScreenWithMenuElements HelpDisplay.lua new file mode 100644 index 0000000000..cdf9d37389 --- /dev/null +++ b/Themes/themekit/Graphics/ScreenWithMenuElements HelpDisplay.lua @@ -0,0 +1,3 @@ +return Def.HelpDisplay { + File = THEME:GetPathF("HelpDisplay", "text"); +}; \ No newline at end of file diff --git a/Themes/themekit/Languages/en.ini b/Themes/themekit/Languages/en.ini new file mode 100644 index 0000000000..9e55b7e42c --- /dev/null +++ b/Themes/themekit/Languages/en.ini @@ -0,0 +1,56 @@ +[Screen] +HelpText=&BACK; Exit &START; Select &SELECT; Options &MENULEFT;&MENURIGHT;&MENUUP;&MENUDOWN; Move + +[ScreenWithMenuElements] +HelpText=&BACK; Exit &START; Select &MENULEFT;&MENURIGHT; Move + +[ScreenTitleMenu] +HelpText=&BACK; Exit &START; Select &MENUUP;&MENUDOWN; Move + +[ScreenTitleJoin] +HelpText=Press &START; to Play +HelpTextJoin=Press &START; to Play +HelpTextWait=Insert Credits... + +[ScreenProfileLoad] +HelpText=... Loading profiles, please wait ... + +[ScreenSelectProfile] +HelpText=&MENUUP;&MENUDOWN; Switch Profile &START; Choose/Join &BACK; Unselect + +[ScreenSelectMaster] +HelpText=&BACK; Exit &START; Select / Join &MENULEFT;&MENURIGHT; Move + +[ScreenSelectPlayMode] +HelpText=&BACK; Exit &START; Select / Join &MENULEFT;&MENURIGHT; Move + +[ScreenSelectPlayStyle] +HelpText=&BACK; Exit &START; Select &MENULEFT;&MENURIGHT; Move + +[ScreenGameInformation] +HelpText=&BACK; Exit &START; Skip + +[ScreenSelectMusic] +HelpText=&BACK; Exit &START; Select / Join &SELECT; Magic Codes &MENULEFT;&MENURIGHT; Move::&AUXWHITE;+[KEY] Sort To [KEY] +AlternateHelpText=&SELECT;+&MENULEFT;&MENURIGHT; Change Difficulties &SELECT;+&START; Quick Sort + +[ScreenSelectCourse] +HelpText=&BACK; Exit &START; Select / Join &SELECT; Magic Codes &MENULEFT;&MENURIGHT; Move::&UP;&DOWN;&UP;&DOWN; for other course types + +[ScreenOptions] +HelpText=&BACK; Exit &START; Choose &SELECT; Go Up &MENULEFT;&MENURIGHT;&MENUUP;&MENUDOWN; Move + +[ScreenStageInformation] +HelpText= + +[ScreenGameplay] +HelpText= + +[ScreenEvaluation] +HelpText=&BACK; Exit &START; Move On &MENULEFT;+&MENURIGHT; or &SELECT; Snapshot + +[OptionNames] +Custom=Special + +[ScreenTestInput] +HelpText=Hold &BACK; or &START; to exit. diff --git a/Themes/themekit/metrics.ini b/Themes/themekit/metrics.ini index 3489476bb4..d499697eee 100644 --- a/Themes/themekit/metrics.ini +++ b/Themes/themekit/metrics.ini @@ -12,29 +12,39 @@ CreditsP2Y=SCREEN_BOTTOM-4 CreditsP2OnCommand=horizalign,right;vertalign,bottom;zoom,0.675;shadowlength,1;diffusebottomedge,ColorLightTone( PlayerColor(PLAYER_2) );strokecolor,Color("Black"); [ScreenWithMenuElements] # Header ( Top of Screen ) +# Header 'Height' is 48px ShowHeader=true HeaderX=SCREEN_CENTER_X -HeaderY=SCREEN_TOP +HeaderY=SCREEN_TOP+4 HeaderOnCommand=vertalign,top;addy,-64;decelerate,0.35;addy,64; HeaderOffCommand= # Text Header ( Text displayed at top of screen on top of header ) ShowTextHeader=true TextHeaderX=SCREEN_CENTER_X-256-32 -TextHeaderY=SCREEN_TOP+32+8-1.5 +TextHeaderY=SCREEN_TOP+32+8+4-1.5 TextHeaderOnCommand=horizalign,left;vertalign,bottom;skewx,-0.125;shadowlength,1;diffusealpha,0;addx,-16;sleep,0.35;decelerate,0.125;diffusealpha,1;addx,16; TextHeaderOffCommand= # Footer ( Bottom Of Screen ) +# Footer 'Height' is 64px ShowFooter=true FooterX=SCREEN_CENTER_X -FooterY=SCREEN_BOTTOM +FooterY=SCREEN_BOTTOM-32 FooterOnCommand=vertalign,bottom;addy,48;decelerate,0.35;addy,-48 FooterOffCommand= # Menu Timer TimerX=SCREEN_CENTER_X+256+32 -TimerY=SCREEN_TOP+32+8-1.5 +TimerY=SCREEN_TOP+32+8+4-1.5 # We animate the timer in [MenuTimer], since diffusion doesn't work here. TimerOnCommand= TimerOffCommand= +# Help Text +ShowHelpDisplay=true +HelpDisplayX=SCREEN_CENTER_X +HelpDisplayY=SCREEN_BOTTOM-32-16 +HelpDisplayOnCommand=SetSecsBetweenSwitches,4;shadowlength,1;draworder,105;zoom,0.675;maxwidth,640/0.675; +HelpDisplayOffCommand=linear,0.175;zoomy,0 +[HelpDisplay] +TipShowTime=4 [MenuTimer] # Text associated with the menutimer Text1OnCommand=stopeffect;stoptweening;horizalign,right;vertalign,bottom;shadowlength,1;diffusealpha,0;x,16;sleep,0.35;decelerate,0.125;diffusealpha,1;x,0; @@ -279,20 +289,29 @@ IconChoiceEndlessDisabledCommand=diffuse,color("1,0,0,0.5"); IconChoiceEndlessOffUnfocusedCommand=linear,0.1175;zoomx,0 IconChoiceEndlessOffFocusedCommand=stopeffect;sleep,0 [ScreenSelectMusic] +BannerX=SCREEN_CENTER_X-128-32 +BannerY=SCREEN_TOP+128-8 +BannerOnCommand=scaletoclipped,256,80 +BannerOffCommand= +# +MusicWheelX=SCREEN_CENTER_X+128+64 +MusicWheelY=SCREEN_CENTER_Y +MusicWheelOnCommand=draworder,-1 +MusicWheelOffCommand= +# + +# ShowStepsDisplayP1=true -StepsDisplayP1X=SCREEN_CENTER_X-192 -StepsDisplayP1Y=SCREEN_BOTTOM-64 +StepsDisplayP1X=SCREEN_CENTER_X-128-32 +StepsDisplayP1Y=SCREEN_BOTTOM-64-16 StepsDisplayP1OnCommand= StepsDisplayP1OffCommand= # ShowStepsDisplayP2=true -StepsDisplayP2X=SCREEN_CENTER_X-192 -StepsDisplayP2Y=SCREEN_BOTTOM-64 +StepsDisplayP2X=SCREEN_CENTER_X+128+32 +StepsDisplayP2Y=SCREEN_BOTTOM-64-16 StepsDisplayP2OnCommand= StepsDisplayP2OffCommand= -# -MusicWheelX=SCREEN_RIGHT-128-18 -MusicWheelOnCommand=draworder,-1 [MusicWheel] HighlightOnCommand=blend,Blend.Add;diffuseramp;effectclock,'beatnooffset' # From 68b391481d9a38a176ad28716224c977c025b113 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 18:19:39 -0400 Subject: [PATCH 083/333] [splittiming] Rewritten to be more modular. Guess I'll have some fun with this tonight. --- src/NotesLoaderKSF.cpp | 255 ++++++++++++++++++++++++++++------------- 1 file changed, 177 insertions(+), 78 deletions(-) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index ca066c3361..862c4bd485 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -9,6 +9,51 @@ #include "Song.h" #include "Steps.h" +static void HandleBunki( TimingData &timing, const float fEarlyBPM, + const float fCurBPM, const float fGap, + const float fPos ) +{ + const float BeatsPerSecond = fEarlyBPM / 60.0f; + const float beat = (fPos + fGap) * BeatsPerSecond; + LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f", + fEarlyBPM, BeatsPerSecond, fPos, beat ); + timing.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), fCurBPM) ); +} + +static bool HandlePipeChars( TimingData &timing, const RString sNoteRow, + const float fCurBeat, int &iTickCount ) +{ + RString temp = sNoteRow.substr(2,sNoteRow.size()-3); + float numTemp = StringToFloat(temp); + if (BeginsWith(sNoteRow, "|T")) + { + iTickCount = static_cast(numTemp); + timing.SetTickcountAtBeat( fCurBeat, clamp(iTickCount, 0, ROWS_PER_BEAT) ); + return true; + } + else if (BeginsWith(sNoteRow, "|B")) + { + timing.SetBPMAtBeat( fCurBeat, numTemp ); + return true; + } + else if (BeginsWith(sNoteRow, "|E")) + { + // Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster + float fCurDelay = 60 / timing.GetBPMAtBeat(fCurBeat) * numTemp / iTickCount; + fCurDelay += timing.GetDelayAtRow(BeatToNoteRow(fCurBeat) ); + timing.SetStopAtBeat( fCurBeat, fCurDelay, true ); + return true; + } + else if (BeginsWith(sNoteRow, "|D")) + { + float fCurDelay = timing.GetStopAtRow(BeatToNoteRow(fCurBeat) ); + fCurDelay += numTemp / 1000; + timing.SetStopAtBeat( fCurBeat, fCurDelay, true ); + return true; + } + return false; +} + static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, bool bKIUCompliant ) { LOG->Trace( "Steps::LoadFromKSFFile( '%s' )", sPath.c_str() ); @@ -25,6 +70,9 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, // According to Aldo_MX, there is a default BPM and it's 60. -aj bool bDoublesChart = false; + + TimingData stepsTiming; + float SMGap1 = 0, SMGap2 = 0, BPM1 = -1, BPMPos2 = -1, BPM2 = -1, BPMPos3 = -1, BPM3 = -1; for( unsigned i=0; iUserLog( "Song file", sPath, "doesn't have a TICKCOUNT. Defaulting to %i.", iTickCount ); } + + // Prepare BPM stuff already if the file uses KSF syntax. + if( bKIUCompliant ) + { + if( BPM2 > 0 && BPMPos2 > 0 ) + { + HandleBunki( stepsTiming, BPM1, BPM2, SMGap1, BPMPos2 ); + } + + if( BPM3 > 0 && BPMPos3 > 0 ) + { + HandleBunki( stepsTiming, BPM2, BPM3, SMGap2, BPMPos3 ); + } + } NoteData notedata; // read it into here @@ -148,6 +291,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, int newTick = -1; float fCurBeat = 0.0f; float prevBeat = 0.0f; // Used for hold tails. + for( unsigned r=0; rUserLog( "Song file", sPath, "has illegal syntax \"%s\" which can't be in KIU complient files.", - sRowString.c_str() ); - return false; - //In other words: you can't mix ksf's with DM05 tags and ksf's without any DM05 tags - //Either one set or another will be read... - }*/ - if( BeginsWith(sRowString, "|B") || BeginsWith(sRowString, "|D") || BeginsWith(sRowString, "|E") ) - { - // TODO: Update for Split Timing. - continue; - } - else if ( BeginsWith(sRowString, "|T") ) - { - RString temp = sRowString.substr(2,sRowString.size()-3); - newTick = StringToInt(temp); - bTickChangeNeeded = true; - out.m_Timing.AddTickcountSegment(TickcountSegment(BeatToNoteRow(fCurBeat), newTick)); + if (bKIUCompliant) + { + // Log an error, ignore the line. + continue; + } + if ( !HandlePipeChars( stepsTiming, sRowString, fCurBeat, iTickCount ) ) + { + // LOG it first. + } continue; + } + else { // Is this why improper ksf or some kiucompilant ksf mixed with dm05 ksf are ignored?? -DaisuMaster @@ -273,6 +408,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, } out.SetNoteData( notedata ); + out.m_Timing = stepsTiming; out.TidyUpData(); @@ -468,21 +604,12 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant { if( BPM2 > 0 && BPMPos2 > 0 ) { - const float BeatsPerSecond = BPM1 / 60.0f; - const float beat = (BPMPos2 + SMGap1) * BeatsPerSecond; - LOG->Trace( "BPM %f, BPS %f, BPMPos2 %f, beat %f", - BPM1, BeatsPerSecond, BPMPos2, beat ); - out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) ); + HandleBunki( out.m_SongTiming, BPM1, BPM2, SMGap1, BPMPos2 ); } if( BPM3 > 0 && BPMPos3 > 0 ) { - const float BeatsPerSecond = BPM2 / 60.0f; - //The line below isn't perfect, but works better than previous versions. - const float beat = (BPMPos3 + SMGap2) * BeatsPerSecond; - LOG->Trace( "BPM %f, BPS %f, BPMPos3 %f, beat %f", - BPM2, BeatsPerSecond, BPMPos3, beat ); - out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) ); + HandleBunki( out.m_SongTiming, BPM2, BPM3, SMGap2, BPMPos3 ); } } else @@ -510,40 +637,11 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant BeginsWith(NoteRowString, "|D") || BeginsWith(NoteRowString, "|E") ) { bDMRequired = true; - RString temp = NoteRowString.substr(2,NoteRowString.size()-3); - float numTemp = StringToFloat(temp); - if (BeginsWith(NoteRowString, "|T")) + if ( !HandlePipeChars( out.m_SongTiming, NoteRowString, fCurBeat, iTickCount ) ) { - iTickCount = (int)numTemp; - TickcountSegment tcs; - tcs.m_iStartRow = BeatToNoteRow(fCurBeat); - tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount; - out.m_SongTiming.AddTickcountSegment( tcs ); - - continue; - } - else if (BeginsWith(NoteRowString, "|B")) - { - float fCurBpm = (float)numTemp; - //out.m_Timing.AddBPMSegment( BPMSegment( BeatToNoteRow(fCurBeat), (float)numTemp ) ); - out.m_SongTiming.SetBPMAtBeat( fCurBeat, fCurBpm ); - continue; - } - else if (BeginsWith(NoteRowString, "|E")) - { - // Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster - float fCurDelay = 60 / out.m_SongTiming.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount; - fCurDelay += out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) ); - out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true ); - continue; - } - else if (BeginsWith(NoteRowString, "|D")) - { - float fCurDelay = out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) ); - fCurDelay += (float)numTemp / 1000; - out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true ); - continue; + // LOG it first. } + continue; } else { @@ -583,16 +681,17 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out ) ASSERT( arrayKSFFileNames.size() ); bool bKIUCompliant = false; - /* If only the first file is read, it will cause problems for other simfiles with - * different BPM changes and tickcounts. This command will probably have to be - * changed in the future. */ + /* With Split Timing, there has to be a backup Song Timing in case + * anything goes wrong. Use the first file found to determine said + * timing, while also establishing whether this file respects the + * Kick It Up syntax. */ if( !LoadGlobalData(out.GetSongDir() + arrayKSFFileNames[0], out, bKIUCompliant) ) return false; // load the Steps from the rest of the KSF files for( unsigned i=0; i Date: Wed, 11 May 2011 20:19:36 -0400 Subject: [PATCH 084/333] Fix linker warning by hand. Library Search Paths weren't showing in Xcode for some reason. --- Xcode/stepmania.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index de7e2b7695..a7c90d60af 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -7203,7 +7203,7 @@ LIBRARY_SEARCH_PATHS = ( "$(SRCROOT)/build/$(CONFIGURATION)", "$(SRCROOT)/Libraries", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; LINKER_DISPLAYS_MANGLED_NAMES = NO; @@ -7316,7 +7316,7 @@ "$(SRCROOT)/Libraries", "$(SRCROOT)/build/$(CONFIGURATION)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; OBJROOT = "$(SRCROOT)/build"; @@ -7364,7 +7364,7 @@ "$(SRCROOT)/Libraries", "$(SRCROOT)/build/$(CONFIGURATION)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; OBJROOT = "$(SRCROOT)/build"; @@ -7414,7 +7414,7 @@ "$(SRCROOT)/Libraries", "$(SRCROOT)/build/$(CONFIGURATION)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; OBJROOT = "$(SRCROOT)/build"; @@ -7849,7 +7849,7 @@ LIBRARY_SEARCH_PATHS = ( "$(SRCROOT)/build/$(CONFIGURATION)", "$(SRCROOT)/Libraries", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; LINKER_DISPLAYS_MANGLED_NAMES = NO; @@ -7926,7 +7926,7 @@ "$(SRCROOT)/Libraries", "$(SRCROOT)/build/$(CONFIGURATION)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; OBJROOT = "$(SRCROOT)/build"; @@ -8078,7 +8078,7 @@ LIBRARY_SEARCH_PATHS = ( "$(SRCROOT)/build/$(CONFIGURATION)", "$(SRCROOT)/Libraries", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; LINKER_DISPLAYS_MANGLED_NAMES = NO; @@ -8206,7 +8206,7 @@ LIBRARY_SEARCH_PATHS = ( "$(SRCROOT)/build/$(CONFIGURATION)", "$(SRCROOT)/Libraries", - "\"$(SRCROOT)/../src/mad-0.15.1b/msvc++/Release\"", + "\"$(SRCROOT)/../extern/mad-0.15.1b/msvc++/Release\"", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build\""; LINKER_DISPLAYS_MANGLED_NAMES = NO; From 0d57fff5e6d2069b886b1d576e525a7e7d783902 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 20:26:47 -0400 Subject: [PATCH 085/333] Get some paths adjusted properly. --- Xcode/stepmania.xcodeproj/project.pbxproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index a7c90d60af..40f00b2e14 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -3308,13 +3308,14 @@ 2BC6132313773C8E00CC8BBD /* pngwutil.c */, ); name = libpng; + path = ../extern/libpng; sourceTree = ""; }; 2BDB87261371F7FF00E6FD3A /* extern */ = { isa = PBXGroup; children = ( EE879B8E132E06C50078FDDC /* glew-1.5.8 */, - EE906F6F12BF3A5B00146C96 /* json */, + EE906F6F12BF3A5B00146C96 /* jsoncpp */, 2BC6130C13773C6800CC8BBD /* libpng */, AA7C8A7F0B6744F600FD9940 /* libtommath */, AA7C8B920B67467C00FD9940 /* libtomcrypt */, @@ -5008,7 +5009,7 @@ path = "../extern/glew-1.5.8"; sourceTree = SOURCE_ROOT; }; - EE906F6F12BF3A5B00146C96 /* json */ = { + EE906F6F12BF3A5B00146C96 /* jsoncpp */ = { isa = PBXGroup; children = ( 2BD06FDD137240CF0018CB9F /* json_batchallocator.h */, @@ -5019,7 +5020,8 @@ 2BD06FE2137240CF0018CB9F /* json_valueiterator.inl */, 2BD06FE3137240CF0018CB9F /* json_writer.cpp */, ); - name = json; + name = jsoncpp; + path = ../extern/jsoncpp; sourceTree = ""; }; /* End PBXGroup section */ From 071616033b5c3d381e01a77024b6967703a04281 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 21:05:56 -0400 Subject: [PATCH 086/333] Never commit code at restaurants again. --- Xcode/stepmania.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 40f00b2e14..b90859f4e1 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -3315,7 +3315,7 @@ isa = PBXGroup; children = ( EE879B8E132E06C50078FDDC /* glew-1.5.8 */, - EE906F6F12BF3A5B00146C96 /* jsoncpp */, + EE906F6F12BF3A5B00146C96 /* json */, 2BC6130C13773C6800CC8BBD /* libpng */, AA7C8A7F0B6744F600FD9940 /* libtommath */, AA7C8B920B67467C00FD9940 /* libtomcrypt */, @@ -5009,7 +5009,7 @@ path = "../extern/glew-1.5.8"; sourceTree = SOURCE_ROOT; }; - EE906F6F12BF3A5B00146C96 /* jsoncpp */ = { + EE906F6F12BF3A5B00146C96 /* json */ = { isa = PBXGroup; children = ( 2BD06FDD137240CF0018CB9F /* json_batchallocator.h */, @@ -5020,7 +5020,7 @@ 2BD06FE2137240CF0018CB9F /* json_valueiterator.inl */, 2BD06FE3137240CF0018CB9F /* json_writer.cpp */, ); - name = jsoncpp; + name = json; path = ../extern/jsoncpp; sourceTree = ""; }; From 4866c126b143d70e6e495b9592655a00ad74235f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 22:01:18 -0400 Subject: [PATCH 087/333] Curious commit here...windows test really. --- src/ScreenInstallOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenInstallOverlay.cpp b/src/ScreenInstallOverlay.cpp index 46c82af0e1..b1037fce23 100644 --- a/src/ScreenInstallOverlay.cpp +++ b/src/ScreenInstallOverlay.cpp @@ -5,7 +5,7 @@ #include "Preference.h" #include "RageLog.h" #include "FileDownload.h" -#include "../extern/jsoncpp/include/json/value.h" +#include "json/value.h" #include "JsonUtil.h" #include "SpecialFiles.h" class Song; From 57aa17bb51f30533e4026249f213e2470f916d80 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 11 May 2011 22:48:19 -0400 Subject: [PATCH 088/333] Slightly desparate, and don't want to lose this. --- src/Makefile.am | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 044b03e9bc..4ffee369a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -389,8 +389,17 @@ Lua = ../extern/lua-5.1/src/lapi.c ../extern/lua-5.1/src/lauxlib.c ../extern/lua ../extern/lua-5.1/src/lstring.h ../extern/lua-5.1/src/ltable.h ../extern/lua-5.1/src/ltm.h ../extern/lua-5.1/src/luaconf.h ../extern/lua-5.1/src/lua.h ../extern/lua-5.1/src/lualib.h \ ../extern/lua-5.1/src/lundump.h ../extern/lua-5.1/src/lvm.h ../extern/lua-5.1/src/lzio.h -jsoncpp = ../extern/jsoncpp/src/lib_json/json_reader.cpp ../extern/jsoncpp/src/lib_json/json_value.cpp \ -../extern/jsoncpp/src/lib_json/json_writer.cpp +jsoncpp = ../extern/jsoncpp/src/lib_json/json_reader.cpp \ +../extern/jsoncpp/src/lib_json/json_value.cpp \ +../extern/jsoncpp/src/lib_json/json_writer.cpp \ +../extern/jsoncpp/include/json/autolink.h \ +../extern/jsoncpp/include/json/config.h \ +../extern/jsoncpp/include/json/features.h \ +../extern/jsoncpp/include/json/forwards.h \ +../extern/jsoncpp/include/json/json.h \ +../extern/jsoncpp/include/json/reader.h \ +../extern/jsoncpp/include/json/value.h \ +../extern/jsoncpp/include/json/writer.h RageFile = \ RageFileBasic.cpp RageFileBasic.h \ From 0e9de47cf6f08e37adc98c5376a116dabac1d0de Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 00:19:01 -0400 Subject: [PATCH 089/333] Patch by codebrainz for linux assistance. Linux users, you may want to make clean && sh ./autogen.sh && ./configure before running make again. --- src/Makefile.am | 9 ++++++--- src/NotesLoaderJson.cpp | 2 +- src/NotesWriterJson.cpp | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4ffee369a3..cff504d81d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -390,9 +390,9 @@ Lua = ../extern/lua-5.1/src/lapi.c ../extern/lua-5.1/src/lauxlib.c ../extern/lua ../extern/lua-5.1/src/lundump.h ../extern/lua-5.1/src/lvm.h ../extern/lua-5.1/src/lzio.h jsoncpp = ../extern/jsoncpp/src/lib_json/json_reader.cpp \ -../extern/jsoncpp/src/lib_json/json_value.cpp \ -../extern/jsoncpp/src/lib_json/json_writer.cpp \ -../extern/jsoncpp/include/json/autolink.h \ +../extern/jsoncpp/src/lib_json/json_value.cpp \ +../extern/jsoncpp/src/lib_json/json_writer.cpp \ +../extern/jsoncpp/include/json/autolink.h \ ../extern/jsoncpp/include/json/config.h \ ../extern/jsoncpp/include/json/features.h \ ../extern/jsoncpp/include/json/forwards.h \ @@ -603,6 +603,8 @@ libtomcrypt_a_CPPFLAGS = -I$(srcdir)/libtomcrypt/src/headers $(AM_CPPFLAGS) noinst_LIBRARIES += libtomcrypt.a +main_CPPFLAGS = -I$(top_srcdir)/extern/jsoncpp/include + main_SOURCES = $(PNG) \ $(Screens) \ $(DataStructures) \ @@ -622,6 +624,7 @@ main_LDADD = \ libtomcrypt.a libtommath.a nodist_stepmania_SOURCES = ver.cpp +stepmania_CPPFLAGS = -I$(top_srcdir)/extern/jsoncpp/include stepmania_SOURCES = $(main_SOURCES) stepmania_LDADD = $(main_LDADD) diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp index 0d44550d97..1c0501114a 100644 --- a/src/NotesLoaderJson.cpp +++ b/src/NotesLoaderJson.cpp @@ -1,6 +1,6 @@ #include "global.h" #include "NotesLoaderJson.h" -#include "Json/Value.h" +#include "json/value.h" #include "TimingData.h" #include "RageUtil.h" #include "JsonUtil.h" diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index 9dfc1d74a8..8bf5186275 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -1,7 +1,7 @@ #include "global.h" #include "NotesWriterJson.h" #include "TimingData.h" -#include "Json/Value.h" +#include "json/value.h" #include "JsonUtil.h" #include "Song.h" #include "BackgroundUtil.h" From ae6dbaa9e22f359aac8dc65b5063d77383a46616 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 00:31:52 -0400 Subject: [PATCH 090/333] Linux compiles again. Needs help linking. --- src/Makefile.am | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index cff504d81d..2a60163c84 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -603,7 +603,8 @@ libtomcrypt_a_CPPFLAGS = -I$(srcdir)/libtomcrypt/src/headers $(AM_CPPFLAGS) noinst_LIBRARIES += libtomcrypt.a -main_CPPFLAGS = -I$(top_srcdir)/extern/jsoncpp/include +main_CPPFLAGS = -I$(top_srcdir)/extern/jsoncpp/include \ +-I$(top_srcdir)/extern/glew-1.5.8/include main_SOURCES = $(PNG) \ $(Screens) \ @@ -624,7 +625,8 @@ main_LDADD = \ libtomcrypt.a libtommath.a nodist_stepmania_SOURCES = ver.cpp -stepmania_CPPFLAGS = -I$(top_srcdir)/extern/jsoncpp/include + +stepmania_CPPFLAGS = $(main_CPPFLAGS) stepmania_SOURCES = $(main_SOURCES) stepmania_LDADD = $(main_LDADD) From fbfbace87d68f2cbd41b778767fc26736e50c55b Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Thu, 12 May 2011 00:57:16 -0500 Subject: [PATCH 091/333] fix crash on start --- src/GameManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/GameManager.cpp b/src/GameManager.cpp index 8709814bdd..a3185e35fb 100644 --- a/src/GameManager.cpp +++ b/src/GameManager.cpp @@ -69,8 +69,10 @@ static const StepsTypeInfo g_StepsTypeInfos[] = { { "ds3ddx-single", 8, true, StepsTypeCategory_Single }, // beatmania { "bm-single5", 6, true, StepsTypeCategory_Single }, // called "bm" for backward compat + { "bm-versus5", 6, true, StepsTypeCategory_Single }, // called "bm" for backward compat { "bm-double5", 12, true, StepsTypeCategory_Double }, // called "bm" for backward compat { "bm-single7", 8, true, StepsTypeCategory_Single }, // called "bm" for backward compat + { "bm-versus7", 8, true, StepsTypeCategory_Single }, // called "bm" for backward compat { "bm-double7", 16, true, StepsTypeCategory_Double }, // called "bm" for backward compat // dance maniax { "maniax-single", 4, true, StepsTypeCategory_Single }, From eda727ddf9840d6c894147865032a0a8924fad3b Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Thu, 12 May 2011 16:44:24 +0700 Subject: [PATCH 092/333] [splittiming] - load split timing from BMS files - fix a crash because autogen'd steps don't inherit the timing from parent - be more verbose in UpdateSongPosition --- src/AutoKeysounds.cpp | 2 +- src/GameState.cpp | 9 +- src/GameState.h | 2 +- src/NotesLoaderBMS.cpp | 408 +++++++++++++++++++++++------------------ src/ScreenEdit.cpp | 4 +- src/ScreenGameplay.cpp | 2 +- src/Steps.cpp | 2 + 7 files changed, 243 insertions(+), 186 deletions(-) diff --git a/src/AutoKeysounds.cpp b/src/AutoKeysounds.cpp index aba066200d..79ec773973 100644 --- a/src/AutoKeysounds.cpp +++ b/src/AutoKeysounds.cpp @@ -99,7 +99,7 @@ void AutoKeysounds::LoadAutoplaySoundsInto( RageSoundReader_Chain *pChain ) if( tn[pn].iKeysoundIndex >= 0 ) { RString sKeysoundFilePath = sSongDir + pSong->m_vsKeysoundFile[tn[pn].iKeysoundIndex]; - float fSeconds = pSong->m_SongTiming.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency(); + float fSeconds = GAMESTATE->m_pCurSteps[pn]->m_Timing.GetElapsedTimeFromBeatNoOffset( NoteRowToBeat(iRow) ) + SOUNDMAN->GetPlayLatency(); float fPan = 0; if( !bSoundIsGlobal ) diff --git a/src/GameState.cpp b/src/GameState.cpp index 4dfbd0ebe6..fd8f2c487b 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -940,14 +940,15 @@ void GameState::ResetStageStatistics() m_iStageSeed = rand(); } -void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) +void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp, bool bUpdatePlayers ) { m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); - FOREACH_EnabledPlayer( pn ) - if( m_pCurSteps[pn] ) - m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); + if( bUpdatePlayers ) + FOREACH_EnabledPlayer( pn ) + if( m_pCurSteps[pn] ) + m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); diff --git a/src/GameState.h b/src/GameState.h index 9b192156c3..000219a343 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -205,7 +205,7 @@ public: static const float MUSIC_SECONDS_INVALID; void ResetMusicStatistics(); // Call this when it's time to play a new song. Clears the values above. - void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); + void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer, bool bUpdatePlayers = false ); float GetSongPercent( float beat ) const; bool AllAreInDangerOrWorse() const; diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index 9eb58168ed..b05f9d8807 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -435,9 +435,121 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t static const int BEATS_PER_MEASURE = 4; static const int ROWS_PER_MEASURE = ROWS_PER_BEAT * BEATS_PER_MEASURE; -static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameToData, Steps &out, - const MeasureToTimeSig_t &sigAdjustments, const map &idToKeySoundIndex ) +static bool SearchForKeysound( const RString &sPath, RString nDataOriginal, map &mapFilenameToKeysoundIndex, Song &out, int &outKeysoundIndex ) { + + // Search for memoized file names: + { + RString nDataToSearchFor = nDataOriginal; + nDataToSearchFor.MakeLower(); + map::iterator it = mapFilenameToKeysoundIndex.find(nDataToSearchFor); + if (it != mapFilenameToKeysoundIndex.end()) { + outKeysoundIndex = it->second; + return true; + } + } + + // FIXME: garbled song names seem to crash the app. + // this might not be the best place to put this code. + if( !utf8_is_valid(nDataOriginal) ) + return false; + + /* Due to bugs in some programs, many BMS files have a "WAV" extension + * on files in the BMS for files that actually have some other extension. + * Do a search. Don't do a wildcard search; if sData is "song.wav", + * we might also have "song.png", which we shouldn't match. */ + RString nData = nDataOriginal; + if( !IsAFile(out.GetSongDir()+nData) ) + { + const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere + for( unsigned i = 0; exts[i] != NULL; ++i ) + { + RString fn = SetExtension( nData, exts[i] ); + if( IsAFile(out.GetSongDir()+fn) ) + { + nData = fn; + break; + } + } + } + + if( !IsAFile(out.GetSongDir()+nData) ) + { + LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() ); + return false; + } + + // Let's again search for memoized file names (we got the normalized one!): + { + RString nDataToSearchFor = nData; + nDataToSearchFor.MakeLower(); + map::iterator it = mapFilenameToKeysoundIndex.find(nDataToSearchFor); + if (it != mapFilenameToKeysoundIndex.end()) { + outKeysoundIndex = it->second; + + { + RString nDataToAdd = nDataOriginal; + nDataToAdd.MakeLower(); + mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex; + } + + return true; + } + } + + // Now this is a new sample. + out.m_vsKeysoundFile.push_back( nData ); + outKeysoundIndex = out.m_vsKeysoundFile.size() - 1; + + { + RString nDataToAdd = nDataOriginal; + nDataToAdd.MakeLower(); + mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex; + } + + { + RString nDataToAdd = nData; + nDataToAdd.MakeLower(); + mapFilenameToKeysoundIndex[nDataToAdd] = outKeysoundIndex; + } + + return true; + +} + +static bool SearchForKeysound( const RString &sPath, RString sNoteId, const NameToData_t &mapNameToData, map &mapIdToKeysoundIndex, map &mapFilenameToKeysoundIndex, Song &out, int &outKeysoundIndex ) +{ + + sNoteId.MakeLower(); + { + map::iterator it = mapIdToKeysoundIndex.find(sNoteId); + if (it != mapIdToKeysoundIndex.end()) + { + outKeysoundIndex = it->second; + return outKeysoundIndex >= 0; + } + } + + RString sTagToLookFor = ssprintf( "#wav%s", sNoteId.c_str() ); + RString nDataOriginal; + if( !GetTagFromMap( mapNameToData, sTagToLookFor, nDataOriginal ) ) + { + LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() ); + return false; + } + + bool retval = SearchForKeysound(sPath, nDataOriginal, mapFilenameToKeysoundIndex, out, outKeysoundIndex); + mapIdToKeysoundIndex[sNoteId] = outKeysoundIndex; + return retval; + +} + +static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameToData, Steps &out, Song &outSong, map &mapFilenameToKeysoundIndex ) +{ + + map mapIdToKeysoundIndex; + MeasureToTimeSig_t sigAdjustments; + LOG->Trace( "Steps::LoadFromBMSFile( '%s' )", sPath.c_str() ); out.m_StepsType = StepsType_Invalid; @@ -453,11 +565,121 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo NoteData ndNotes; ndNotes.SetNumTracks( NUM_BMS_TRACKS ); + // Read BPM + if( GetTagFromMap(mapNameToData, "#bpm", sData) ) + { + const float fBPM = StringToFloat( sData ); + + if( fBPM > 0.0f ) + { + BPMSegment newSeg( 0, fBPM ); + out.m_Timing.AddBPMSegment( newSeg ); + LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); + } + else + { + LOG->UserLog( "Song file", sPath.c_str(), "has an invalid BPM change at beat %f, BPM %f.", + NoteRowToBeat(0), fBPM ); + } + } + + /* Read time signatures. Note that these can differ across files in the same * song. */ MeasureToTimeSig_t mapMeasureToTimeSig; ReadTimeSigs( mapNameToData, mapMeasureToTimeSig ); + for( NameToData_t::const_iterator it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it ) + { + const RString &sName = it->first; + if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) ) + continue; + // this is step or offset data. Looks like "#00705" + int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); + int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() ); + int iStepIndex = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); + float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustments ); + int iRowsPerMeasure = BeatToNoteRow( fBeatsPerMeasure ); + + RString nData = it->second; + int totalPairs = nData.size() / 2; + for( int i = 0; i < totalPairs; ++i ) + { + RString sPair = nData.substr( i*2, 2 ); + + int iRow = iStepIndex + (i * iRowsPerMeasure) / totalPairs; + float fBeat = NoteRowToBeat( iRow ); + int iVal = 0; + sscanf( sPair, "%x", &iVal ); + + if (sPair == "00") + { + continue; + } + + switch( iBMSTrackNo ) + { + case BMS_TRACK_BPM: + if( iVal > 0 ) + { + out.m_Timing.SetBPMAtBeat( fBeat, (float) iVal ); + LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal ); + } + else + { + LOG->UserLog( "Song file", sPath.c_str(), "has an invalid BPM change at beat %f, BPM %d.", + fBeat, iVal ); + } + break; + + case BMS_TRACK_BPM_REF: + { + RString sTagToLookFor = ssprintf( "#bpm%s", sPair.c_str() ); + RString sBPM; + if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) ) + { + float fBPM = StringToFloat( sBPM ); + out.m_Timing.SetBPMAtBeat( fBeat, fBPM ); + } + else + { + LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() ); + } + break; + } + case BMS_TRACK_STOP: + { + if( iVal == 0 ) + { + break; + } + RString sTagToLookFor = ssprintf( "#stop%02x", iVal ); + RString sBeats; + if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) ) + { + // find the BPM at the time of this freeze + float fBPS = out.m_Timing.GetBPMAtBeat(fBeat) / 60.0f; + float fBeats = StringToFloat( sBeats ) / 48.0f; + float fFreezeSecs = fBeats / fBPS; + + StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs ); + out.m_Timing.AddStopSegment( newSeg ); + LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds ); + } + else + { + LOG->UserLog( "Song file", sPath.c_str(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() ); + } + break; + } + } + } + + } + + // Now that we're done reading BPMs, factor out weird time signatures. + SetTimeSigAdjustments( mapMeasureToTimeSig, outSong, sigAdjustments ); + int iHoldStarts[NUM_BMS_TRACKS]; TapNote iHoldHeads[NUM_BMS_TRACKS]; @@ -487,10 +709,9 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo RString sNoteId = sNoteData.substr( i, 2 ); if( sNoteId != "00" ) { - vTapNotes.push_back( TAP_ORIGINAL_TAP ); - map::const_iterator rInt = idToKeySoundIndex.find( sNoteId ); - if( rInt != idToKeySoundIndex.end() ) - vTapNotes.back().iKeysoundIndex = rInt->second; + TapNote tn = TAP_ORIGINAL_TAP; + SearchForKeysound( sPath, sNoteId, mapNameToData, mapIdToKeysoundIndex, mapFilenameToKeysoundIndex, outSong, tn.iKeysoundIndex ); + vTapNotes.push_back( tn ); } else { @@ -781,7 +1002,7 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo return true; } -static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, MeasureToTimeSig_t &sigAdjustmentsOut, map &idToKeySoundIndexOut ) +static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out ) { RString sData; if( GetTagFromMap(mapNameToData, "#title", sData) ) @@ -792,172 +1013,6 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur GetTagFromMap( mapNameToData, "#backbmp", out.m_sBackgroundFile ); GetTagFromMap( mapNameToData, "#wav", out.m_sMusicFile ); - if( GetTagFromMap(mapNameToData, "#bpm", sData) ) - { - const float fBPM = StringToFloat( sData ); - - if( PREFSMAN->m_bQuirksMode ) - { - BPMSegment newSeg( 0, fBPM ); - out.m_SongTiming.AddBPMSegment( newSeg ); - if( fBPM > 0.0f ) - LOG->Trace( "Inserting new positive BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); - else - LOG->Trace( "Inserting new negative BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); - } - else - { - if( fBPM > 0.0f ) - { - BPMSegment newSeg( 0, fBPM ); - out.m_SongTiming.AddBPMSegment( newSeg ); - LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); - } - else - { - LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %f.", - NoteRowToBeat(0), fBPM ); - } - } - } - - NameToData_t::const_iterator it; - for( it = mapNameToData.lower_bound("#wav"); it != mapNameToData.end(); ++it ) - { - const RString &sName = it->first; - - if( sName.size() != 6 || sName.Left(4) != "#wav" ) - continue; - - // this is keysound file name. Looks like "#WAV1A" - RString nData = it->second; - RString sWavID = sName.Right(2); - - // FIXME: garbled song names seem to crash the app. - // this might not be the best place to put this code. - if( !utf8_is_valid(nData) ) - continue; - - /* Due to bugs in some programs, many BMS files have a "WAV" extension - * on files in the BMS for files that actually have some other extension. - * Do a search. Don't do a wildcard search; if sData is "song.wav", - * we might also have "song.png", which we shouldn't match. */ - if( !IsAFile(out.GetSongDir()+nData) ) - { - const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere - for( unsigned i = 0; exts[i] != NULL; ++i ) - { - RString fn = SetExtension( nData, exts[i] ); - if( IsAFile(out.GetSongDir()+fn) ) - { - nData = fn; - break; - } - } - } - if( !IsAFile(out.GetSongDir()+nData) ) - LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() ); - - sWavID.MakeUpper(); // HACK: undo the MakeLower() - out.m_vsKeysoundFile.push_back( nData ); - idToKeySoundIndexOut[ sWavID ] = out.m_vsKeysoundFile.size()-1; - LOG->Trace( "Inserting keysound index %u '%s'", unsigned(out.m_vsKeysoundFile.size()-1), sWavID.c_str() ); - } - - // Time signature tags affect all other global timing tags, so read them first. - MeasureToTimeSig_t mapMeasureToTimeSig; - ReadTimeSigs( mapNameToData, mapMeasureToTimeSig ); - - for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it ) - { - const RString &sName = it->first; - if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) ) - continue; - // this is step or offset data. Looks like "#00705" - int iMeasureNo = atoi( sName.substr(1, 3).c_str() ); - int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() ); - int iStepIndex = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut ); - float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustmentsOut ); - int iRowsPerMeasure = BeatToNoteRow( fBeatsPerMeasure ); - - RString nData = it->second; - int totalPairs = nData.size() / 2; - for( int i = 0; i < totalPairs; ++i ) - { - RString sPair = nData.substr( i*2, 2 ); - - int iRow = iStepIndex + (i * iRowsPerMeasure) / totalPairs; - float fBeat = NoteRowToBeat( iRow ); - int iVal = 0; - sscanf( sPair, "%x", &iVal ); - - if (sPair == "00") - { - continue; - } - - switch( iBMSTrackNo ) - { - case BMS_TRACK_BPM: - if( iVal > 0 ) - { - out.m_SongTiming.SetBPMAtBeat( fBeat, (float) iVal ); - LOG->Trace( "Inserting new BPM change at beat %f, BPM %i", fBeat, iVal ); - } - else - { - LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %d.", - fBeat, iVal ); - } - break; - - case BMS_TRACK_BPM_REF: - { - RString sTagToLookFor = ssprintf( "#bpm%s", sPair.c_str() ); - RString sBPM; - if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) ) - { - float fBPM = StringToFloat( sBPM ); - out.m_SongTiming.SetBPMAtBeat( fBeat, fBPM ); - } - else - { - LOG->UserLog( "Song file", out.GetSongDir(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() ); - } - break; - } - case BMS_TRACK_STOP: - { - if( iVal == 0 ) - { - break; - } - RString sTagToLookFor = ssprintf( "#stop%02x", iVal ); - RString sBeats; - if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) ) - { - // find the BPM at the time of this freeze - float fBPS = out.m_SongTiming.GetBPMAtBeat(fBeat) / 60.0f; - float fBeats = StringToFloat( sBeats ) / 48.0f; - float fFreezeSecs = fBeats / fBPS; - - StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs ); - out.m_SongTiming.AddStopSegment( newSeg ); - LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds ); - } - else - { - LOG->UserLog( "Song file", out.GetSongDir(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() ); - } - break; - } - } - } - - } - - // Now that we're done reading BPMs, factor out weird time signatures. - SetTimeSigAdjustments( mapMeasureToTimeSig, out, sigAdjustmentsOut ); } static void SlideDuplicateDifficulties( Song &p ) @@ -1100,9 +1155,7 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out ) if( apSteps[i]->GetDifficulty() == Difficulty_Medium ) iMainDataIndex = i; - MeasureToTimeSig_t sigAdjustments; - map idToKeysoundIndex; - ReadGlobalTags( aBMSData[iMainDataIndex], out, sigAdjustments, idToKeysoundIndex ); + ReadGlobalTags( aBMSData[iMainDataIndex], out ); // The brackets before the difficulty are in common substring, so remove them if it's found. if( commonSubstring.size() > 2 && commonSubstring[commonSubstring.size() - 2] == ' ' ) @@ -1124,10 +1177,11 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out ) // Now that we've parsed the keysound data, load the Steps from the rest // of the .bms files. + map mapFilenameToKeysoundIndex; for( unsigned i=0; iGetPositionSeconds( NULL, &tm ); - GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm ); + GAMESTATE->UpdateSongPosition( fSeconds, GAMESTATE->m_pCurSong->m_SongTiming, tm, true ); } if( m_EditState == STATE_RECORDING ) @@ -2388,7 +2388,7 @@ void ScreenEdit::TransitionEditState( EditState em ) /* Give a 1 second lead-in. If we're loading Player, this must be done first. */ float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; - GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing ); + GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing, RageZeroTimer, true ); GAMESTATE->m_bGameplayLeadIn.Set( false ); diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 041613e914..ffea34a274 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1423,7 +1423,7 @@ void ScreenGameplay::UpdateSongPosition( float fDeltaTime ) RageTimer tm; const float fSeconds = m_pSoundMusic->GetPositionSeconds( NULL, &tm ); const float fAdjust = SOUND->GetFrameTimingAdjustment( fDeltaTime ); - GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust ); + GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, GAMESTATE->m_pCurSong->m_SongTiming, tm+fAdjust, true ); } void ScreenGameplay::BeginScreen() diff --git a/src/Steps.cpp b/src/Steps.cpp index 3c0cf7cb57..5c2c91f063 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -339,6 +339,7 @@ void Steps::AutogenFrom( const Steps *parent_, StepsType ntTo ) { parent = parent_; m_StepsType = ntTo; + m_Timing = parent->m_Timing; } void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ) // pSource does not have to be of the same StepsType @@ -348,6 +349,7 @@ void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds pSource->GetNoteData( noteData ); noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks ); parent = NULL; + m_Timing = pSource->m_Timing; this->SetNoteData( noteData ); this->SetDescription( pSource->GetDescription() ); this->SetDifficulty( pSource->GetDifficulty() ); From 6847ef9087dcfe5e10d35030251d4072dc2d67b4 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Thu, 12 May 2011 17:11:54 +0700 Subject: [PATCH 093/333] [splittiming] Now that we have split timing, Compress/Expand in ScreenEdit no longer need to affect any other notes anymore. --- src/ScreenEdit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 5d1eb1d933..217e515554 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3507,6 +3507,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns m_pSteps->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); // scale all other steps. + /* const vector sIter = m_pSong->GetAllSteps(); RString sTempStyle, sTempDiff; for( unsigned i = 0; i < sIter.size(); i++ ) @@ -3525,7 +3526,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::ScaleRegion( ndTemp, fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker ); sIter[i]->SetNoteData( ndTemp ); } - + */ m_NoteFieldEdit.m_iEndMarker = iNewEndIndex; } From a09e3d51c2e2ad5502ce4df917e54d0832973556 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Thu, 12 May 2011 19:07:41 +0700 Subject: [PATCH 094/333] [splittiming] - calculate m_fFirstBeat and m_fLastBeat correctly - fix a crash caused by calculating by tidying the timing first. - make editor go back to right place after playing (the editor should be fairly working now!) --- src/ScreenEdit.cpp | 4 ++-- src/Song.cpp | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 217e515554..8b9e03cb0d 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2372,11 +2372,11 @@ void ScreenEdit::TransitionEditState( EditState em ) GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fBeatToReturnTo; // Make sure we're snapped. - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); /* Playing and recording have lead-ins, which may start before beat 0; * make sure we don't stay there if we escaped out early. */ - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = max( GAMESTATE->m_Position.m_fSongBeat, 0 ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = max( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, 0 ); break; diff --git a/src/Song.cpp b/src/Song.cpp index dcb39b1eec..8bf3c72fd0 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -472,6 +472,13 @@ void Song::TidyUpData() m_fMusicLengthSeconds = 0; } + m_SongTiming.TidyUpData(); + + FOREACH( Steps *, m_vpSteps, s ) + { + (*s)->m_Timing.TidyUpData(); + } + /* Generate these before we autogen notes, so the new notes can inherit * their source's values. */ ReCalculateRadarValuesAndLastBeat(); @@ -488,13 +495,6 @@ void Song::TidyUpData() m_sArtist = "Unknown artist"; TranslateTitles(); - m_SongTiming.TidyUpData(); - - FOREACH( Steps *, m_vpSteps, s ) - { - (*s)->m_Timing.TidyUpData(); - } - if( m_fMusicSampleStartSeconds == -1 || m_fMusicSampleStartSeconds == 0 || m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) @@ -833,8 +833,8 @@ void Song::ReCalculateRadarValuesAndLastBeat() if( tempNoteData.GetLastRow() == 0 ) continue; - fFirstBeat = min( fFirstBeat, tempNoteData.GetFirstBeat() ); - fLastBeat = max( fLastBeat, tempNoteData.GetLastBeat() ); + fFirstBeat = min( fFirstBeat, m_SongTiming.GetBeatFromElapsedTime(pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetFirstBeat())) ); + fLastBeat = max( fLastBeat, m_SongTiming.GetBeatFromElapsedTime(pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetLastBeat())) ); } m_fFirstBeat = fFirstBeat; From 24ddc948ed03c0876d48c38948f14563811baea3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 11:18:21 -0400 Subject: [PATCH 095/333] Stops and Delays need length, not BPMs. --- src/NoteField.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NoteField.h b/src/NoteField.h index 23502eca00..560f3cb563 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -56,7 +56,7 @@ protected: void DrawMarkerBar( int fBeat ); void DrawAreaHighlight( int iStartBeat, int iEndBeat ); void DrawBPMText( const float fBeat, const float fBPM ); - void DrawFreezeText( const float fBeat, const float fBPM, const float bDelay ); + void DrawFreezeText( const float fBeat, const float fLength, const float bDelay ); void DrawWarpText( const float fBeat, const float fNewBeat ); void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ); void DrawTickcountText( const float fBeat, int iTicks ); From 7c0ea4cc8a12404b1bbf81f8a19997c47e4b00c9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 12:21:17 -0400 Subject: [PATCH 096/333] Fake note fix by Jousway. --- NoteSkins/dance/midi-note/NoteSkin.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/NoteSkins/dance/midi-note/NoteSkin.lua b/NoteSkins/dance/midi-note/NoteSkin.lua index 2ae3231d5f..d821c2740b 100644 --- a/NoteSkins/dance/midi-note/NoteSkin.lua +++ b/NoteSkins/dance/midi-note/NoteSkin.lua @@ -29,7 +29,12 @@ ret.Redir = function(sButton, sElement) then sElement = "Hold Head Inactive"; end - + + if sElement == "Tap Fake" + then + sElement = "Tap Note"; + end + sButton = ret.RedirTable[sButton]; return sButton, sElement; @@ -85,6 +90,7 @@ ret.PartsToRotate = ["Tap Explosion Bright"] = true, ["Tap Explosion Dim"] = true, ["Tap Note"] = true, + ["Tap Fake"] = true, ["Tap Lift"] = true, ["Hold Head Active"] = true, ["Hold Head Inactive"] = true, From b22bd332f5c0a095eef00fc23de1ed2560f2d697 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Thu, 12 May 2011 23:23:15 +0700 Subject: [PATCH 097/333] Disable the use of precompiled headers for libpng. --- src/StepMania-net2008.vcproj | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index 2dfb5b7eb1..fdd1456e75 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -6586,6 +6586,14 @@ + + + @@ -6610,6 +6618,14 @@ + + + @@ -6622,6 +6638,14 @@ + + + @@ -6642,6 +6666,14 @@ + + + @@ -6654,6 +6686,14 @@ + + + @@ -6670,6 +6710,14 @@ + + + @@ -6682,6 +6730,14 @@ + + + @@ -6694,6 +6750,14 @@ + + + @@ -6706,6 +6770,14 @@ + + + @@ -6718,6 +6790,14 @@ + + + @@ -6734,6 +6814,14 @@ + + + @@ -6746,6 +6834,14 @@ + + + @@ -6758,6 +6854,14 @@ + + + @@ -6770,6 +6874,14 @@ + + + @@ -6782,6 +6894,14 @@ + + + From 83c5b676476dc97409dc2b03498653aa92337472 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Thu, 12 May 2011 23:34:57 +0700 Subject: [PATCH 098/333] [splittiming] - #include "global.h" in SongPosition.cpp to make it build in MSVC. - Add SongPosition.cpp to VC2008 project. --- src/SongPosition.cpp | 1 + src/StepMania-net2008.vcproj | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 048c93708c..79e925658f 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -1,3 +1,4 @@ +#include "global.h" #include "SongPosition.h" static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index fdd1456e75..a038f0dc1d 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -1444,6 +1444,14 @@ RelativePath="SongOptions.h" > + + + + From fcf393215999b6137e00a6aba67d02ce5808f46d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 12:35:05 -0400 Subject: [PATCH 099/333] Attempted default noteskin fake fix. Am I the only one that isn't getting the desired results? --- NoteSkins/dance/default/metrics.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NoteSkins/dance/default/metrics.ini b/NoteSkins/dance/default/metrics.ini index 5845c92a82..016f99edee 100644 --- a/NoteSkins/dance/default/metrics.ini +++ b/NoteSkins/dance/default/metrics.ini @@ -8,6 +8,7 @@ TapNoteAnimationLength=1 // none of these matter because Lua is handling the ani TapAdditionAnimationLength=1 TapMineAnimationLength=1 TapLiftAnimationLength=1 +TapFakeAnimationLength=1 HoldHeadAnimationLength=1 HoldTopCapAnimationLength=1 HoldBottomCapAnimationLength=1 @@ -30,6 +31,8 @@ TapNoteAdditionTextureCoordOffsetX=0 TapNoteAdditionTextureCoordOffsetY=0 TapNoteNoteColorTextureCoordSpacingX=0 TapNoteNoteColorTextureCoordSpacingY=.125 +TapFakeNoteColorTextureCoordSpacingX=0 +TapFakeNoteColorTextureCoordSpacingY=.125 HoldHeadNoteColorTextureCoordSpacingX=0 HoldHeadNoteColorTextureCoordSpacingY=.125 From fa07ab9e0a2439f4143e9718b0c31d4ef096bc71 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 13:19:51 -0400 Subject: [PATCH 100/333] Doxygen bot commit test. --- src/NoteSkinManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NoteSkinManager.cpp b/src/NoteSkinManager.cpp index e8d6cb9901..d56062e0df 100644 --- a/src/NoteSkinManager.cpp +++ b/src/NoteSkinManager.cpp @@ -16,7 +16,8 @@ #include #include "SpecialFiles.h" -NoteSkinManager* NOTESKIN = NULL; // global object accessable from anywhere in the program +/** @brief Have the NoteSkinManager available throughout the program. */ +NoteSkinManager* NOTESKIN = NULL; const RString GAME_COMMON_NOTESKIN_NAME = "common"; const RString GAME_BASE_NOTESKIN_NAME = "default"; From 1f51dec22caf5a986ca53e345e5427f93ccb583b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 14:39:42 -0400 Subject: [PATCH 101/333] Fix initialization warning. --- src/Course.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Course.cpp b/src/Course.cpp index dec0b75526..8993e8b44b 100644 --- a/src/Course.cpp +++ b/src/Course.cpp @@ -90,8 +90,8 @@ int CourseEntry::GetNumModChanges() const Course::Course(): m_bIsAutogen(false), m_sPath(""), m_sMainTitle(""), m_sMainTitleTranslit(""), m_sSubTitle(""), m_sSubTitleTranslit(""), - m_sBannerPath(""), m_sBackgroundPath(""), m_sCDTitlePath(""), - m_sGroupName(""), m_sScripter(""), m_bRepeat(false), m_fGoalSeconds(0), + m_sScripter(""), m_sBannerPath(""), m_sBackgroundPath(""), + m_sCDTitlePath(""), m_sGroupName(""), m_bRepeat(false), m_fGoalSeconds(0), m_bShuffle(false), m_iLives(-1), m_bSortByMeter(false), m_bIncomplete(false), m_vEntries(), m_SortOrder_TotalDifficulty(0), m_SortOrder_Ranking(0), m_LoadedFromProfile(ProfileSlot_Invalid), From 6f6e8edd3079ce34b384a8fd5c312207a73514b3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 15:32:09 -0400 Subject: [PATCH 102/333] Another warning, another bot test. --- src/RageSound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RageSound.cpp b/src/RageSound.cpp index a89ff3018a..f114329fbc 100644 --- a/src/RageSound.cpp +++ b/src/RageSound.cpp @@ -51,7 +51,7 @@ RageSound::RageSound(): m_Mutex( "RageSound" ), m_pSource(NULL), m_sFilePath(""), m_Param(), m_iStreamFrame(0), m_iStoppedSourceFrame(0), m_bPlaying(false), - m_sError(""), m_bDeleteWhenFinished(false) + m_bDeleteWhenFinished(false), m_sError("") { ASSERT( SOUNDMAN ); } From c2ab2e9bb893f57f045a41c512076dd3db32f29e Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Thu, 12 May 2011 16:54:51 -0500 Subject: [PATCH 103/333] hello world and some line endings crap; midi really needs to set up hgeol in his client --- Themes/HelloWorld/Graphics/_section Guide.png | Bin 267 -> 310 bytes .../Graphics/_section Reference.png | Bin 297 -> 329 bytes .../HelloWorld/Graphics/_section Tutorial.png | Bin 313 -> 347 bytes .../default.lua | 26 +++++++++--------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Themes/HelloWorld/Graphics/_section Guide.png b/Themes/HelloWorld/Graphics/_section Guide.png index 18cd4a69a8d4732c8370f3b3ae554c0aff5250fe..5a1ed471abfb913486627a2b98deb7ac3bc3fca6 100644 GIT binary patch delta 183 zcmV;o07(Cf0=5E>V+jQe6*MTKX-pE4Y$$(?Nkl%sK!YXN7 zSO=E_v60oH%V9GET@N;SumdLPEYRwTMV)UpZQ=1@bmM- z1(00}(u^#Jt`-*?mmIp;x0laiWWg3JAlFj^pgRf{B`^R=e<%)sxe#3=y6f=)WOXBI lQR#Ti06B3%#2&hW`Z%Ynb^!{K^FjNqNaoJnSFctEJh3mfFzI=QWKzi t2qOycSxl^>@P#0{86bJa0nY^k4FK#)kYC}tzJmY&002ovPDHLkV1n@pIdA{~ diff --git a/Themes/HelloWorld/Graphics/_section Reference.png b/Themes/HelloWorld/Graphics/_section Reference.png index a5d7c0b2b2edf821fd944e778c5ceaedc743c2d1..e322d8b4b162646b097f8d5ae19244e568c1d8a3 100644 GIT binary patch delta 202 zcmV;*05$)q0?7i9V+jQe6*MfR1c(cfY$$)ANklPfzcHD?*n;2Go)x*FI{v6C42i{QPhMP-r3ZVQl131ce+m zc%0C0hkAjg6n z7-~`JVEWdwnHT{Dlfwoml_S?aYPgdHT>zV*=;G)Gkt;{8eT2a6<+B)JY~(DCZYD?_ z3ob*@Eu}>YAlE)Z09Uz&ZYEeAavnj?FU008bPGw*N3MPN%pt{0MrzdpxRTu{7~~cJ Y00BDpPaJbF#sB~S07*qoM6N<$f+wOxH~;_u diff --git a/Themes/HelloWorld/Graphics/_section Tutorial.png b/Themes/HelloWorld/Graphics/_section Tutorial.png index a0fc39758c1cf40fb47df4dc7149ba54a4b507d4..c724cb427c32246a2cfd3e6364adca994edd3530 100644 GIT binary patch delta 220 zcmV<203-jo0^0(RV+jQe6*Mi<1Gt@$Y$$)SNklacm11w_~u)`2;vr+0yA)66os0uBxi6b;CHV)VhpU}}h! zBSjrnkHMl5Kn o*Mv$;Y-)(nM{7W8b{J9s0R5ly{gOc_<^TWy07*qoM6N<$g5)kvIRF3v diff --git a/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua b/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua index 72fd7fce4a..7376c470a3 100644 --- a/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua +++ b/Themes/themekit/BGAnimations/ScreenWithMenuElements underlay/default.lua @@ -1,14 +1,14 @@ -local t = Def.ActorFrame { - InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y); -}; --- -t[#t+1] = LoadActor("grid") .. { - InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/16,SCREEN_HEIGHT/16); - OnCommand=cmd(diffuse,color("0,0,0,0.125")); -}; -t[#t+1] = LoadActor("grid") .. { - InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/32,SCREEN_HEIGHT/32); - OnCommand=cmd(diffuse,color("0,0,0,0.25")); -}; --- +local t = Def.ActorFrame { + InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y); +}; +-- +t[#t+1] = LoadActor("grid") .. { + InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/16,SCREEN_HEIGHT/16); + OnCommand=cmd(diffuse,color("0,0,0,0.125")); +}; +t[#t+1] = LoadActor("grid") .. { + InitCommand=cmd(zoomto,SCREEN_WIDTH,SCREEN_HEIGHT;customtexturerect,0,0,SCREEN_WIDTH/32,SCREEN_HEIGHT/32); + OnCommand=cmd(diffuse,color("0,0,0,0.25")); +}; +-- return t \ No newline at end of file From f9da743e59104adf14a8aed452758d90ed208811 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 20:50:38 -0400 Subject: [PATCH 104/333] [splittiming] Fix editor bug on create & no save. Hmm...is this bug also in default? --- src/NoteField.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 5f76e23d3e..06f73b18d1 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -739,10 +739,12 @@ void NoteField::DrawPrimitives() cur->m_ReceptorArrowRow.Draw(); } + Steps *stepChecking = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]; + // Draw beat bars - if( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) + if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && stepChecking != NULL ) { - const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing.m_vTimeSignatureSegments; + const vector &vTimeSignatureSegments = stepChecking->m_Timing.m_vTimeSignatureSegments; int iMeasureIndex = 0; FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter ) { @@ -781,11 +783,11 @@ void NoteField::DrawPrimitives() } } - if( GAMESTATE->IsEditing() ) + if( GAMESTATE->IsEditing() && stepChecking != NULL ) { ASSERT(GAMESTATE->m_pCurSong); - const TimingData &timing = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing; + const TimingData &timing = stepChecking->m_Timing; // BPM text FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg ) From 1ee92c65e98f11b0fa31bf5b769e670deadf2e2e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 20:55:45 -0400 Subject: [PATCH 105/333] [splittiming] Allow F1^H4 dedicated Timing Menu. --- src/ScreenEdit.cpp | 39 ++++++++++++++++++++++++++------------- src/ScreenEdit.h | 4 ++++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8b9e03cb0d..9427fb8ee6 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -194,6 +194,9 @@ void ScreenEdit::InitEditMappings() return; case EditMode_Full: + // F4 = Show timing menu + m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_TIMING_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_F4); + /* Don't allow F5/F6 in home mode. It breaks the "delay creation until first save" logic. */ m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_PREV_STEPS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_F5); m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_NEXT_STEPS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_F6); @@ -1522,6 +1525,11 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_OPEN_INPUT_HELP: DoHelp(); break; + case EDIT_BUTTON_OPEN_TIMING_MENU: + { + DisplayTimingMenu(); + break; + } case EDIT_BUTTON_OPEN_NEXT_STEPS: case EDIT_BUTTON_OPEN_PREV_STEPS: { @@ -3056,6 +3064,23 @@ static void ChangeMaxBPM( const RString &sNew ) GAMESTATE->m_pCurSong->m_fSpecifiedBPMMax = StringToFloat( sNew ); } +void ScreenEdit::DisplayTimingMenu() +{ + TimingData pTime = m_pSteps->m_Timing; + const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; + g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); + g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); + + EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); +} + // End helper functions static LocalizedString REVERT_LAST_SAVE ( "ScreenEdit", "Do you want to revert to your last save?" ); @@ -3259,19 +3284,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns break; case edit_timing_data: { - TimingData pTime = m_pSteps->m_Timing; - const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; - g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; - g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); - g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); - - EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); + DisplayTimingMenu(); } break; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index ea10ca22a2..58656f419a 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -86,6 +86,7 @@ enum EditButton EDIT_BUTTON_SNAP_PREV, EDIT_BUTTON_OPEN_EDIT_MENU, + EDIT_BUTTON_OPEN_TIMING_MENU, EDIT_BUTTON_OPEN_AREA_MENU, EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU, EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU, @@ -231,6 +232,9 @@ protected: float GetMaximumBeatForMoving() const; // don't allow Down key to go past this beat. void DoHelp(); + + /** @brief Display the TimingData menu for editing song and step timing. */ + void DisplayTimingMenu(); EditState m_EditState; From 5bcc094504fa21d61a9337bb17128ad65f25afb5 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 21:23:48 -0400 Subject: [PATCH 106/333] [splittiming] Let Steps have their own offset. There are pros and cons...call this one instinct. --- src/ScreenEdit.cpp | 21 +++++++++++---------- src/ScreenEdit.h | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 9427fb8ee6..2186924579 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -551,7 +551,6 @@ static MenuDef g_SongInformation( MenuRowDef( ScreenEdit::main_title_transliteration, "Main title transliteration", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::sub_title_transliteration, "Sub title transliteration", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::artist_transliteration, "Artist transliteration", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::last_beat_hint, "Last beat hint", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::preview_start, "Preview Start", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::preview_length, "Preview Length", true, EditMode_Full, true, true, 0, NULL ), @@ -562,7 +561,8 @@ static MenuDef g_SongInformation( static MenuDef g_TimingDataInformation( "ScreenMiniMenuTimingDataInformation", - MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::stop, "Edit stop", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), @@ -3068,6 +3068,7 @@ void ScreenEdit::DisplayTimingMenu() { TimingData pTime = m_pSteps->m_Timing; const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); @@ -3271,7 +3272,6 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit ); g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit ); g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit ); - g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_SongTiming.m_fBeat0OffsetInSeconds) ); g_SongInformation.rows[last_beat_hint].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedLastBeat) ); g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds) ); g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds) ); @@ -3679,7 +3679,6 @@ static LocalizedString ENTER_CREDIT ("ScreenEdit","Enter a new credit."); static LocalizedString ENTER_MAIN_TITLE_TRANSLIT ("ScreenEdit","Enter a new main title transliteration."); static LocalizedString ENTER_SUB_TITLE_TRANSLIT ("ScreenEdit","Enter a new sub title transliteration."); static LocalizedString ENTER_ARTIST_TRANSLIT ("ScreenEdit","Enter a new artist transliteration."); -static LocalizedString ENTER_BEAT_0_OFFSET ("ScreenEdit","Enter the offset for the song."); static LocalizedString ENTER_LAST_BEAT_HINT ("ScreenEdit","Enter a new last beat hint."); static LocalizedString ENTER_PREVIEW_START ("ScreenEdit","Enter a new preview start."); static LocalizedString ENTER_PREVIEW_LENGTH ("ScreenEdit","Enter a new preview length."); @@ -3716,11 +3715,6 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec case artist_transliteration: ScreenTextEntry::TextEntry( SM_None, ENTER_ARTIST_TRANSLIT, pSong->m_sArtistTranslit, 100, NULL, ChangeArtistTranslit, NULL ); break; - case beat_0_offset: - ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, - ssprintf("%.5f", m_pSteps->m_Timing.m_fBeat0OffsetInSeconds), 20, - ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); - break; case last_beat_hint: ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_BEAT_HINT, ssprintf("%.5f", pSong->m_fSpecifiedLastBeat), 20, @@ -3749,6 +3743,8 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec }; } + +static LocalizedString ENTER_BEAT_0_OFFSET ("ScreenEdit","Enter the offset for the song."); static LocalizedString ENTER_BPM_VALUE ( "ScreenEdit", "Enter a new BPM value." ); static LocalizedString ENTER_STOP_VALUE ( "ScreenEdit", "Enter a new Stop value." ); static LocalizedString ENTER_DELAY_VALUE ( "ScreenEdit", "Enter a new Delay value." ); @@ -3763,7 +3759,12 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice switch( c ) { DEFAULT_FAIL( c ); - case bpm: + case beat_0_offset: + ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, + ssprintf("%.5f", m_pSteps->m_Timing.m_fBeat0OffsetInSeconds), 20, + ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); + break; + case bpm: ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 58656f419a..a24053645f 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -463,7 +463,6 @@ public: main_title_transliteration, sub_title_transliteration, artist_transliteration, - beat_0_offset, last_beat_hint, preview_start, preview_length, @@ -476,6 +475,7 @@ public: enum TimingDataInformationChoice { + beat_0_offset, bpm, stop, delay, From 7c638451cd271862f70626692b8dd67bad594f7a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 21:31:33 -0400 Subject: [PATCH 107/333] [splittiming] Write out the Steps' #OFFSET. --- src/NotesWriterSSC.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index d24f7f5e9f..445aa9ee5b 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -132,7 +132,6 @@ static void GetTimingTags( vector &lines, TimingData timing ) FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls ) w.Write( ls->m_iStartRow, ls->m_sLabel.c_str() ); w.Finish(); - } static void WriteTimingTags( RageFile &f, const TimingData &timing ) @@ -147,7 +146,7 @@ static void WriteTimingTags( RageFile &f, const TimingData &timing ) } /** - * @brief Write out the common tags for .SM files. + * @brief Write out the common tags for .SSC files. * @param f the file in question. * @param out the Song in question. */ static void WriteGlobalTags( RageFile &f, const Song &out ) @@ -299,6 +298,9 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa GetTimingTags( lines, in.m_Timing ); + lines.push_back( "#ATTACKS:;" ); // not sure of how to handle this yet. + lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) ); + RString sNoteData; in.GetSMNoteData( sNoteData ); From 4edf884b1ae1fb7d7035ddfd205d6fc259232b5f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 21:41:20 -0400 Subject: [PATCH 108/333] [splittiming] Cleanup and comment. --- src/ScreenEdit.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 2186924579..221d527996 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3036,6 +3036,9 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { + /* TODO: Use a switch/boolean to determine which to write to. + * If it's a new chart (have to find a way to determine that), + * write to both. */ GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } @@ -3744,7 +3747,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec } -static LocalizedString ENTER_BEAT_0_OFFSET ("ScreenEdit","Enter the offset for the song."); +static LocalizedString ENTER_BEAT_0_OFFSET ( "ScreenEdit", "Enter the offset for the song."); static LocalizedString ENTER_BPM_VALUE ( "ScreenEdit", "Enter a new BPM value." ); static LocalizedString ENTER_STOP_VALUE ( "ScreenEdit", "Enter a new Stop value." ); static LocalizedString ENTER_DELAY_VALUE ( "ScreenEdit", "Enter a new Delay value." ); From 32afac99918b2a4c2e925f2d4fe1739487079016 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 22:07:00 -0400 Subject: [PATCH 109/333] [splittiming] Fit more text/directions in. Someone more skilled in metrics can try to make the text stand out. --- Themes/_fallback/Languages/en.ini | 2 +- Themes/_fallback/metrics.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index d0492d5a94..b4f91ef808 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1246,7 +1246,7 @@ Enter a new min BPM.=Enter the minimum displayed BPM. Enter a new max BPM.=Enter the maximum displayed BPM. More than %d notes per measure is not allowed. This change has been reverted.=More than %d notes per measure is not allowed. This change has been reverted. No backgrounds available=No backgrounds available -EditHelpText=Up/Down:\n change beat\nLeft/Right:\n change snap\nNumber keys:\n add/remove\n tap note\nCreate hold note:\n Hold a number\n while moving\n Up or Down\nCreate roll note:\n Hold Shift,\n then create a\n hold note.\nSpace bar:\n Set area\n marker\nEnter:\n Area Menu\nEscape:\n Main Menu\nF1:\n Show help\n +EditHelpText=Up/Down:\n change beat\nLeft/Right:\n change snap\nNumber keys:\n add/remove\n tap note\nN and M keys:\n swap tap notes\nCreate hold note:\n Hold a number\n while moving\n Up or Down\nCreate roll note:\n Hold Shift,\n then create a\n hold note.\nSpace bar:\n Set area\n marker\nEnter:\n Area Menu\nEscape:\n Main Menu\nF4:\n Timing Menu\nF1:\n Show help\n PlayRecordHelpText=Press START to end Save successful.=Save successful. Saved as SM and DWI.=Saved as SM and DWI. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 668d96827b..ecac994d7e 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3598,7 +3598,7 @@ TimerSeconds=-1 EditModifiers="no reverse" EditHelpX=SCREEN_LEFT+4 EditHelpY=SCREEN_TOP+16 -EditHelpOnCommand=halign,0;valign,0;zoom,0.675;shadowlength,1 +EditHelpOnCommand=halign,0;valign,0;zoom,0.5;shadowlength,1 InfoX=SCREEN_RIGHT-128 InfoY=SCREEN_TOP+16 InfoOnCommand=halign,0;valign,0;zoom,0.5;shadowlength,1 From 29e0bd3d2f668eece62a856d5e8ba3f7f2eb588b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 22:24:25 -0400 Subject: [PATCH 110/333] [splittiming] Prepare timing bool switch. This is needed in GAMESTATE due to it also going to be called in NoteField. --- src/GameState.cpp | 3 ++- src/GameState.h | 41 +++++++++++++++++++++++++++++++++++------ src/ScreenEdit.cpp | 5 +++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 242ccaee70..4a521e1ebb 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -127,7 +127,8 @@ GameState::GameState() : m_pEditSourceSteps( Message_EditSourceStepsChanged ), m_stEditSource( Message_EditSourceStepsTypeChanged ), m_iEditCourseEntryIndex( Message_EditCourseEntryIndexChanged ), - m_sEditLocalProfileID( Message_EditLocalProfileIDChanged ) + m_sEditLocalProfileID( Message_EditLocalProfileIDChanged ), + m_bIsEditorStepTiming( false ) { g_pImpl = new GameStateImpl; diff --git a/src/GameState.h b/src/GameState.h index 000219a343..592b613dfe 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -44,7 +44,8 @@ public: void ResetPlayer( PlayerNumber pn ); void ApplyCmdline(); // called by Reset void ApplyGameCommand( const RString &sCommand, PlayerNumber pn=PLAYER_INVALID ); - void BeginGame(); // called when first player joins + /** @brief Start the game when the first player joins in. */ + void BeginGame(); void JoinPlayer( PlayerNumber pn ); void UnjoinPlayer( PlayerNumber pn ); bool JoinInput( PlayerNumber pn ); @@ -56,13 +57,25 @@ public: bool HaveProfileToSave(); void SaveLocalData(); void LoadCurrentSettingsFromProfile( PlayerNumber pn ); - void SaveCurrentSettingsToProfile( PlayerNumber pn ); // called at the beginning of each stage + /** + * @brief Save the specified player's settings to his/her profile. + * + * This is called at the beginning of each stage. + * @param pn the PlayerNumber to save the stats to. */ + void SaveCurrentSettingsToProfile( PlayerNumber pn ); Song* GetDefaultSong() const; void Update( float fDelta ); // Main state info - void SetCurGame( const Game *pGame ); // Call this instead of m_pCurGame.Set to make sure PREFSMAN->m_sCurrentGame stays in sync + + /** + * @brief State what the current game is. + * + * Call this instead of m_pCurGame.Set to make sure that + * PREFSMAN->m_sCurrentGame stays in sync. + * @param pGame the game to start using. */ + void SetCurGame( const Game *pGame ); BroadcastOnChangePtr m_pCurGame; BroadcastOnChangePtr m_pCurStyle; /** @brief Determine which side is joined. @@ -130,6 +143,9 @@ public: bool IsCourseMode() const; bool IsBattleMode() const; // not Rave + /** + * @brief Do we show the W1 timing judgment? + * @return true if we do, or false otherwise. */ bool ShowW1() const; BroadcastOnChange m_sPreferredSongGroup; // GROUP_ALL denotes no preferred group @@ -142,7 +158,11 @@ public: SortOrder m_PreferredSortOrder; // used by MusicWheel EditMode m_EditMode; bool IsEditing() const { return m_EditMode != EditMode_Invalid; } - bool m_bDemonstrationOrJukebox; // ScreenGameplay does special stuff when this is true + /** + * @brief Are we in the demonstration or jukebox mode? + * + * ScreenGameplay often does special things when this is set to true. */ + bool m_bDemonstrationOrJukebox; bool m_bJukeboxUsesModifiers; int m_iNumStagesOfThisSong; /** @@ -240,8 +260,11 @@ public: // Options stuff ModsGroup m_SongOptions; - // True if the current mode has changed the default NoteSkin, such as Edit/Sync Songs does. - // Note: any mode that wants to use it must set it + /** + * @brief Did the current game mode change the default Noteskin? + * + * This is true if it has: see Edit/Sync Songs for a common example. + * Note: any mode that wants to use this must set it explicitly. */ bool m_bDidModeChangeNoteSkin; void GetDefaultPlayerOptions( PlayerOptions &po ); @@ -308,6 +331,12 @@ public: Premium GetPremium() const; // Edit stuff + + /** + * @brief Is the editor making changes to Song timing or Steps timing? + * + * Different options are available depending on this setting. */ + bool m_bIsEditorStepTiming; BroadcastOnChange m_stEdit; BroadcastOnChange m_cdEdit; BroadcastOnChangePtr m_pEditSourceSteps; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 221d527996..43f8b94d46 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -692,6 +692,8 @@ REGISTER_SCREEN_CLASS( ScreenEdit ); void ScreenEdit::Init() { m_pSoundMusic = NULL; + + GAMESTATE->m_bIsEditorStepTiming = true; SubscribeToMessage( "Judgment" ); @@ -849,6 +851,9 @@ ScreenEdit::~ScreenEdit() LOG->Trace( "ScreenEdit::~ScreenEdit()" ); m_pSoundMusic->StopPlaying(); + + // Reset the GameState variable in case it's needed elsewhere. + GAMESTATE->m_bIsEditorStepTiming = false; } void ScreenEdit::BeginScreen() From 3a348123ca52c4b682fcfc5f48330624c99af624 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 22:34:16 -0400 Subject: [PATCH 111/333] [splittiming] Draw certain text based on switch. Note: the diff for this hates the indentation. --- src/NoteField.cpp | 145 ++++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 68 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 06f73b18d1..66cdf2a34b 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -833,25 +833,31 @@ void NoteField::DrawPrimitives() } } - // Tickcount text - FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg ) + if( GAMESTATE->m_bIsEditorStepTiming ) { - if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + // Tickcount text + FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg ) { - float fBeat = NoteRowToBeat(seg->m_iStartRow); - if( IS_ON_SCREEN(fBeat) ) - DrawTickcountText( fBeat, seg->m_iTicks ); + if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + { + float fBeat = NoteRowToBeat(seg->m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawTickcountText( fBeat, seg->m_iTicks ); + } } } - // Combo text - FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg ) + if( GAMESTATE->m_bIsEditorStepTiming ) { - if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + // Combo text + FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg ) { - float fBeat = NoteRowToBeat(seg->m_iStartRow); - if( IS_ON_SCREEN(fBeat) ) - DrawComboText( fBeat, seg->m_iCombo ); + if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + { + float fBeat = NoteRowToBeat(seg->m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawComboText( fBeat, seg->m_iCombo ); + } } } @@ -886,71 +892,74 @@ void NoteField::DrawPrimitives() } } } - - // BGChange text - switch( GAMESTATE->m_EditMode ) + + if( !GAMESTATE->m_bIsEditorStepTiming ) { - case EditMode_Home: - case EditMode_CourseMods: - case EditMode_Practice: - break; - case EditMode_Full: - { - vector::iterator iter[NUM_BackgroundLayer]; - FOREACH_BackgroundLayer( i ) - iter[i] = GAMESTATE->m_pCurSong->GetBackgroundChanges(i).begin(); - - while( 1 ) + // BGChange text + switch( GAMESTATE->m_EditMode ) + { + case EditMode_Home: + case EditMode_CourseMods: + case EditMode_Practice: + break; + case EditMode_Full: { - float fLowestBeat = FLT_MAX; - vector viLowestIndex; - + vector::iterator iter[NUM_BackgroundLayer]; FOREACH_BackgroundLayer( i ) + iter[i] = GAMESTATE->m_pCurSong->GetBackgroundChanges(i).begin(); + + while( 1 ) { - if( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() ) - continue; - - float fBeat = iter[i]->m_fStartBeat; - if( fBeat < fLowestBeat ) - { - fLowestBeat = fBeat; - viLowestIndex.clear(); - viLowestIndex.push_back( i ); - } - else if( fBeat == fLowestBeat ) - { - viLowestIndex.push_back( i ); - } - } - - if( viLowestIndex.empty() ) - { + float fLowestBeat = FLT_MAX; + vector viLowestIndex; + FOREACH_BackgroundLayer( i ) - ASSERT( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() ); - break; - } - - if( IS_ON_SCREEN(fLowestBeat) ) - { - vector vsBGChanges; - FOREACH_CONST( BackgroundLayer, viLowestIndex, i ) { - ASSERT( iter[*i] != GAMESTATE->m_pCurSong->GetBackgroundChanges(*i).end() ); - const BackgroundChange& change = *iter[*i]; - RString s = change.GetTextDescription(); - if( *i!=0 ) - s = ssprintf("%d: ",*i) + s; - vsBGChanges.push_back( s ); + if( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() ) + continue; + + float fBeat = iter[i]->m_fStartBeat; + if( fBeat < fLowestBeat ) + { + fLowestBeat = fBeat; + viLowestIndex.clear(); + viLowestIndex.push_back( i ); + } + else if( fBeat == fLowestBeat ) + { + viLowestIndex.push_back( i ); + } } - DrawBGChangeText( fLowestBeat, join("\n",vsBGChanges) ); + + if( viLowestIndex.empty() ) + { + FOREACH_BackgroundLayer( i ) + ASSERT( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() ); + break; + } + + if( IS_ON_SCREEN(fLowestBeat) ) + { + vector vsBGChanges; + FOREACH_CONST( BackgroundLayer, viLowestIndex, i ) + { + ASSERT( iter[*i] != GAMESTATE->m_pCurSong->GetBackgroundChanges(*i).end() ); + const BackgroundChange& change = *iter[*i]; + RString s = change.GetTextDescription(); + if( *i!=0 ) + s = ssprintf("%d: ",*i) + s; + vsBGChanges.push_back( s ); + } + DrawBGChangeText( fLowestBeat, join("\n",vsBGChanges) ); + } + FOREACH_CONST( BackgroundLayer, viLowestIndex, i ) + iter[*i]++; } - FOREACH_CONST( BackgroundLayer, viLowestIndex, i ) - iter[*i]++; } - } - break; - default: - ASSERT(0); + break; + default: + ASSERT(0); + } } // Draw marker bars From 59fe8c02c069564fb7e92b46ba0d9edbfec4e391 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 22:39:10 -0400 Subject: [PATCH 112/333] [splittiming] Organize Beat 0 Offset. --- src/ScreenEdit.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 43f8b94d46..fcd2910e30 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1139,7 +1139,11 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Home: break; case EditMode_Full: - sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), m_pSteps->m_Timing.m_fBeat0OffsetInSeconds ); + sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), + BEAT_0_OFFSET.GetValue().c_str(), + ( GAMESTATE->m_bIsEditorStepTiming ? + m_pSteps->m_Timing.m_fBeat0OffsetInSeconds : + m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds ) ); sText += ssprintf( PREVIEW_START_FORMAT.GetValue(), PREVIEW_START.GetValue().c_str(), m_pSong->m_fMusicSampleStartSeconds ); sText += ssprintf( PREVIEW_LENGTH_FORMAT.GetValue(), PREVIEW_LENGTH.GetValue().c_str(), m_pSong->m_fMusicSampleLengthSeconds ); break; @@ -3041,10 +3045,12 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - /* TODO: Use a switch/boolean to determine which to write to. - * If it's a new chart (have to find a way to determine that), - * write to both. */ - GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); + TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; + if( GAMESTATE->m_bIsEditorStepTiming ) + { + timing = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing; + } + timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } static void ChangeLastBeatHint( const RString &sNew ) From d74294d4b7811da65e7f163b2b219607efa0a052 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 22:50:39 -0400 Subject: [PATCH 113/333] [splittiming] DisplayTimingMenu() The bottom part may be reverted if this backfires horribly. --- src/ScreenEdit.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index fcd2910e30..abf1260948 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3080,16 +3080,29 @@ static void ChangeMaxBPM( const RString &sNew ) void ScreenEdit::DisplayTimingMenu() { - TimingData pTime = m_pSteps->m_Timing; - const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + float fBeat; + TimingData &pTime = m_pSteps->m_Timing; + if( !GAMESTATE->m_bIsEditorStepTiming ) + { + pTime = m_pSong->m_SongTiming; + fBeat = GAMESTATE->m_Position.m_fSongBeat; + } + else + { + fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + } + g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + if( GAMESTATE->m_bIsEditorStepTiming ) + { + g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + } g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); From 7361e3fe04ed0989908ff7e39fd7ae3af243c27e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 23:01:19 -0400 Subject: [PATCH 114/333] [splittiming] GetAppropriateTiming() function. I admit it: I got tired of typing the same if statement. --- src/ScreenEdit.cpp | 34 ++++++++++++++++++++-------------- src/ScreenEdit.h | 5 +++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index abf1260948..0113f41682 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1141,9 +1141,7 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Full: sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), - ( GAMESTATE->m_bIsEditorStepTiming ? - m_pSteps->m_Timing.m_fBeat0OffsetInSeconds : - m_pSong->m_SongTiming.m_fBeat0OffsetInSeconds ) ); + GetAppropriateTiming().m_fBeat0OffsetInSeconds ); sText += ssprintf( PREVIEW_START_FORMAT.GetValue(), PREVIEW_START.GetValue().c_str(), m_pSong->m_fMusicSampleStartSeconds ); sText += ssprintf( PREVIEW_LENGTH_FORMAT.GetValue(), PREVIEW_LENGTH.GetValue().c_str(), m_pSong->m_fMusicSampleLengthSeconds ); break; @@ -2648,21 +2646,21 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fBPM > 0 ) - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fBPM ); + GetAppropriateTiming().SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fStop ); + GetAppropriateTiming().SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fDelay, true ); + GetAppropriateTiming().SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2670,7 +2668,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - m_pSteps->m_Timing.SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iNum ); + GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iNum ); } SetDirty( true ); } @@ -2679,7 +2677,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - m_pSteps->m_Timing.SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iDen ); + GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iDen ); } SetDirty( true ); } @@ -2688,7 +2686,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - m_pSteps->m_Timing.SetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iTick ); + GetAppropriateTiming().SetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iTick ); } SetDirty( true ); } @@ -2697,7 +2695,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - m_pSteps->m_Timing.SetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iCombo ); + GetAppropriateTiming().SetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iCombo ); } SetDirty( true ); } @@ -2708,14 +2706,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - m_pSteps->m_Timing.SetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, sLabel ); + GetAppropriateTiming().SetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - m_pSteps->m_Timing.SetWarpAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fWarp ); + GetAppropriateTiming().SetWarpAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -3078,13 +3076,21 @@ static void ChangeMaxBPM( const RString &sNew ) GAMESTATE->m_pCurSong->m_fSpecifiedBPMMax = StringToFloat( sNew ); } +TimingData & ScreenEdit::GetAppropriateTiming() const +{ + if( GAMESTATE->m_bIsEditorStepTiming ) + { + return m_pSteps->m_Timing; + } + return m_pSong->m_SongTiming; +} + void ScreenEdit::DisplayTimingMenu() { float fBeat; - TimingData &pTime = m_pSteps->m_Timing; + TimingData &pTime = GetAppropriateTiming(); if( !GAMESTATE->m_bIsEditorStepTiming ) { - pTime = m_pSong->m_SongTiming; fBeat = GAMESTATE->m_Position.m_fSongBeat; } else diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index a24053645f..f471a6a9f1 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -548,6 +548,11 @@ public: void MakeFilteredMenuDef( const MenuDef* pDef, MenuDef &menu ); void EditMiniMenu( const MenuDef* pDef, ScreenMessage SM_SendOnOK = SM_None, ScreenMessage SM_SendOnCancel = SM_None ); +private: + /** + * @brief Retrieve the appropriate TimingData based on GAMESTATE. + * @return the proper TimingData. */ + TimingData & GetAppropriateTiming() const; }; #endif From 14fc0839d528dd39105bd51c405d83009799442b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 23:11:42 -0400 Subject: [PATCH 115/333] [splittiming] Prepare right side of editor. Now, what key on the keyboard can be used for switching... --- Themes/_fallback/Languages/en.ini | 3 +++ Themes/_fallback/metrics.ini | 1 + src/ScreenEdit.cpp | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index b4f91ef808..98a6d9c2e7 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1276,6 +1276,9 @@ Mines=Mines Rolls=Rolls Lifts=Lifts Fakes=Fakes +Timing Mode=Timing Mode +Step Timing=Step Timing +Song Timing=Song Timing Beat 0 offset=Beat 0 offset Preview Start=Preview Start Preview Length=Preview Length diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index ecac994d7e..9423e563fb 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3627,6 +3627,7 @@ NumHandsFormat="%s: %d\n" NumRollsFormat="%s: %d\n" NumLiftsFormat="%s: %d\n" NumFakesFormat="%s: %d\n" +TimingModeFormat="%:\n %s\n" Beat0OffsetFormat="%s:\n %.5f secs\n" PreviewStartFormat="%s:\n %.5f secs\n" PreviewLengthFormat="%s:\n %.5f secs\n" diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0113f41682..d05063d0ad 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1035,6 +1035,9 @@ static LocalizedString MINES("ScreenEdit", "Mines"); static LocalizedString ROLLS("ScreenEdit", "Rolls"); static LocalizedString LIFTS("ScreenEdit", "Lifts"); static LocalizedString FAKES("ScreenEdit", "Fakes"); +static LocalizedString TIMING_MODE("ScreenEdit", "Timing Mode"); +static LocalizedString STEP_TIMING("ScreenEdit", "Step Timing"); +static LocalizedString SONG_TIMING("ScreenEdit", "Song Timing"); static LocalizedString BEAT_0_OFFSET("ScreenEdit", "Beat 0 offset"); static LocalizedString PREVIEW_START("ScreenEdit", "Preview Start"); static LocalizedString PREVIEW_LENGTH("ScreenEdit", "Preview Length"); @@ -1060,6 +1063,7 @@ static ThemeMetric NUM_HANDS_FORMAT("ScreenEdit", "NumHandsFormat"); static ThemeMetric NUM_ROLLS_FORMAT("ScreenEdit", "NumRollsFormat"); static ThemeMetric NUM_LIFTS_FORMAT("ScreenEdit", "NumLiftsFormat"); static ThemeMetric NUM_FAKES_FORMAT("ScreenEdit", "NumFakesFormat"); +static ThemeMetric TIMING_MODE_FORMAT("ScreenEdit", "TimingModeFormat"); static ThemeMetric BEAT_0_OFFSET_FORMAT("ScreenEdit", "Beat0OffsetFormat"); static ThemeMetric PREVIEW_START_FORMAT("ScreenEdit", "PreviewStartFormat"); static ThemeMetric PREVIEW_LENGTH_FORMAT("ScreenEdit", "PreviewLengthFormat"); @@ -1139,6 +1143,11 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Home: break; case EditMode_Full: + sText += ssprintf( TIMING_MODE_FORMAT.GetValue(), + TIMING_MODE.GetValue().c_str(), + ( GAMESTATE->m_bIsEditorStepTiming ? + STEP_TIMING.GetValue().c_str() : + SONG_TIMING.GetValue().c_str() ) ); sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), BEAT_0_OFFSET.GetValue().c_str(), GetAppropriateTiming().m_fBeat0OffsetInSeconds ); From 64a6abc12ba87f2174d31f99ce0c2de69e66c34d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 23:18:57 -0400 Subject: [PATCH 116/333] [splittiming] Add the [T]iming Switch. One or two more things to do before running this... --- Themes/_fallback/Languages/en.ini | 1 + src/ScreenEdit.cpp | 9 +++++++++ src/ScreenEdit.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 98a6d9c2e7..e6c4a64c23 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1956,6 +1956,7 @@ Cycle between tap notes=Cycle between tap notes Lay mine=Lay mine Lay lift=Lay lift Add to/remove from right half=Add to/remove from right half +Switch Timing=Switch Timing Switch player (Routine only)=Switch player (Routine only) [Grade] diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index d05063d0ad..a12f22580f 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -310,6 +310,9 @@ void ScreenEdit::InitEditMappings() // Switch players, if it makes sense to do so. m_EditMappingsDeviceInput.button[EDIT_BUTTON_SWITCH_PLAYERS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_SLASH); + + // Allow song and step timing to be swapped. + m_EditMappingsDeviceInput.button[EDIT_BUTTON_SWITCH_TIMINGS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Ct); m_PlayMappingsDeviceInput.button[EDIT_BUTTON_RETURN_TO_EDIT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ESC); m_PlayMappingsMenuButton.button[EDIT_BUTTON_RETURN_TO_EDIT][1] = GAME_BUTTON_BACK; @@ -2105,6 +2108,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) m_InputPlayerNumber = PLAYER_1; } break; + + case EDIT_BUTTON_SWITCH_TIMINGS: + GAMESTATE->m_bIsEditorStepTiming = !GAMESTATE->m_bIsEditorStepTiming; + break; } } @@ -4190,6 +4197,7 @@ struct EditHelpLine #undef PUSH_IF_VALID } }; +// TODO: Identify which of these can be removed and sent to a readme. static const EditHelpLine g_EditHelpLines[] = { EditHelpLine( "Move cursor", EDIT_BUTTON_SCROLL_UP_LINE, EDIT_BUTTON_SCROLL_DOWN_LINE ), @@ -4218,6 +4226,7 @@ static const EditHelpLine g_EditHelpLines[] = EditHelpLine( "Shift BPM changes and stops up one beat", EDIT_BUTTON_DELETE_SHIFT_PAUSES ), EditHelpLine( "Cycle between tap notes", EDIT_BUTTON_CYCLE_TAP_LEFT, EDIT_BUTTON_CYCLE_TAP_RIGHT ), EditHelpLine( "Add to/remove from right half", EDIT_BUTTON_RIGHT_SIDE ), + EditHelpLine( "Switch Timing", EDIT_BUTTON_SWITCH_TIMINGS ), EditHelpLine( "Switch player (Routine only)", EDIT_BUTTON_SWITCH_PLAYERS ), }; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index f471a6a9f1..eb36e539e2 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -138,6 +138,8 @@ enum EditButton EDIT_BUTTON_ADD_COURSE_MODS, EDIT_BUTTON_SWITCH_PLAYERS, /**< Allow entering notes for a different Player. */ + + EDIT_BUTTON_SWITCH_TIMINGS, /**< Allow switching between Song and Step TimingData. */ NUM_EditButton, // leave this at the end EditButton_Invalid From 72690b8c70314a31723de3088ee021b4811f866e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 12 May 2011 23:25:50 -0400 Subject: [PATCH 117/333] [splittiming] BG stuff in Song Timing only. Alright...let's see how badly I broke this. --- Themes/_fallback/Languages/en.ini | 2 +- src/ScreenEdit.cpp | 179 +++++++++++++++--------------- 2 files changed, 92 insertions(+), 89 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index e6c4a64c23..a2014d3f75 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1947,7 +1947,7 @@ Decrease/increase music offset=Decrease/increase music offset Decrease/increase sample music start=Decrease/increase sample music start Decrease/increase sample music length=Decrease/increase sample music length Play sample music=Play sample music -Add/Edit Background Change=Add/Edit Background Change +Add/Edit Background Change=Add/Edit Background Change (Song Timing Only) Insert beat and shift down=Insert beat and shift down Shift BPM changes and stops down one beat=Shift BPM changes and stops down one beat Delete beat and shift up=Delete beat and shift up diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index a12f22580f..7c738bac1e 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1798,101 +1798,104 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU: case EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU: - switch( EditB ) + if( !GAMESTATE->m_bIsEditorStepTiming ) { - DEFAULT_FAIL( EditB ); - case EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU: g_CurrentBGChangeLayer = BACKGROUND_LAYER_1; break; - case EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU: g_CurrentBGChangeLayer = BACKGROUND_LAYER_2; break; - } - - { - // Fill in option names - vector vThrowAway; - - MenuDef &menu = g_BackgroundChange; - - menu.rows[layer].choices[0] = ssprintf("%d",g_CurrentBGChangeLayer); - BackgroundUtil::GetBackgroundTransitions( "", vThrowAway, menu.rows[transition].choices ); - g_BackgroundChange.rows[transition].choices.insert( g_BackgroundChange.rows[transition].choices.begin(), "None" ); // add "no transition" - BackgroundUtil::GetBackgroundEffects( "", vThrowAway, menu.rows[effect].choices ); - menu.rows[effect].choices.insert( menu.rows[effect].choices.begin(), "Default" ); // add "default effect" - - BackgroundUtil::GetSongBGAnimations( m_pSong, "", vThrowAway, menu.rows[file1_song_bganimation].choices ); - BackgroundUtil::GetSongMovies( m_pSong, "", vThrowAway, menu.rows[file1_song_movie].choices ); - BackgroundUtil::GetSongBitmaps( m_pSong, "", vThrowAway, menu.rows[file1_song_still].choices ); - BackgroundUtil::GetGlobalBGAnimations( m_pSong, "", vThrowAway, menu.rows[file1_global_bganimation].choices ); // NULL to get all background files - BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie].choices, false, false ); // all backgrounds - BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie_song_group].choices, false, true ); // song group's backgrounds - BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie_song_group_and_genre].choices, true, true ); // song group and genre's backgrounds - - menu.rows[file2_type].choices = menu.rows[file1_type].choices; - menu.rows[file2_song_bganimation].choices = menu.rows[file1_song_bganimation].choices; - menu.rows[file2_song_movie].choices = menu.rows[file1_song_movie].choices; - menu.rows[file2_song_still].choices = menu.rows[file1_song_still].choices; - menu.rows[file2_global_bganimation].choices = menu.rows[file1_global_bganimation].choices; - menu.rows[file2_global_movie].choices = menu.rows[file1_global_movie].choices; - menu.rows[file2_global_movie_song_group].choices = menu.rows[file1_global_movie_song_group].choices; - menu.rows[file2_global_movie_song_group_and_genre].choices = menu.rows[file1_global_movie_song_group_and_genre].choices; - - - // Fill in lines enabled/disabled - bool bAlreadyBGChangeHere = false; - BackgroundChange bgChange; - FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(g_CurrentBGChangeLayer), bgc ) + switch( EditB ) { - if( bgc->m_fStartBeat == GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) - { - bAlreadyBGChangeHere = true; - bgChange = *bgc; - } + DEFAULT_FAIL( EditB ); + case EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU: g_CurrentBGChangeLayer = BACKGROUND_LAYER_1; break; + case EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU: g_CurrentBGChangeLayer = BACKGROUND_LAYER_2; break; } + { + // Fill in option names + vector vThrowAway; + + MenuDef &menu = g_BackgroundChange; + + menu.rows[layer].choices[0] = ssprintf("%d",g_CurrentBGChangeLayer); + BackgroundUtil::GetBackgroundTransitions( "", vThrowAway, menu.rows[transition].choices ); + g_BackgroundChange.rows[transition].choices.insert( g_BackgroundChange.rows[transition].choices.begin(), "None" ); // add "no transition" + BackgroundUtil::GetBackgroundEffects( "", vThrowAway, menu.rows[effect].choices ); + menu.rows[effect].choices.insert( menu.rows[effect].choices.begin(), "Default" ); // add "default effect" + + BackgroundUtil::GetSongBGAnimations( m_pSong, "", vThrowAway, menu.rows[file1_song_bganimation].choices ); + BackgroundUtil::GetSongMovies( m_pSong, "", vThrowAway, menu.rows[file1_song_movie].choices ); + BackgroundUtil::GetSongBitmaps( m_pSong, "", vThrowAway, menu.rows[file1_song_still].choices ); + BackgroundUtil::GetGlobalBGAnimations( m_pSong, "", vThrowAway, menu.rows[file1_global_bganimation].choices ); // NULL to get all background files + BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie].choices, false, false ); // all backgrounds + BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie_song_group].choices, false, true ); // song group's backgrounds + BackgroundUtil::GetGlobalRandomMovies( m_pSong, "", vThrowAway, menu.rows[file1_global_movie_song_group_and_genre].choices, true, true ); // song group and genre's backgrounds + + menu.rows[file2_type].choices = menu.rows[file1_type].choices; + menu.rows[file2_song_bganimation].choices = menu.rows[file1_song_bganimation].choices; + menu.rows[file2_song_movie].choices = menu.rows[file1_song_movie].choices; + menu.rows[file2_song_still].choices = menu.rows[file1_song_still].choices; + menu.rows[file2_global_bganimation].choices = menu.rows[file1_global_bganimation].choices; + menu.rows[file2_global_movie].choices = menu.rows[file1_global_movie].choices; + menu.rows[file2_global_movie_song_group].choices = menu.rows[file1_global_movie_song_group].choices; + menu.rows[file2_global_movie_song_group_and_genre].choices = menu.rows[file1_global_movie_song_group_and_genre].choices; + + + // Fill in lines enabled/disabled + bool bAlreadyBGChangeHere = false; + BackgroundChange bgChange; + FOREACH( BackgroundChange, m_pSong->GetBackgroundChanges(g_CurrentBGChangeLayer), bgc ) + { + if( bgc->m_fStartBeat == GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) + { + bAlreadyBGChangeHere = true; + bgChange = *bgc; + } + } + #define FILL_ENABLED( x ) menu.rows[x].bEnabled = menu.rows[x].choices.size() > 0; - FILL_ENABLED( transition ); - FILL_ENABLED( effect ); - FILL_ENABLED( file1_song_bganimation ); - FILL_ENABLED( file1_song_movie ); - FILL_ENABLED( file1_song_still ); - FILL_ENABLED( file1_global_bganimation ); - FILL_ENABLED( file1_global_movie ); - FILL_ENABLED( file1_global_movie_song_group ); - FILL_ENABLED( file1_global_movie_song_group_and_genre ); - FILL_ENABLED( file2_song_bganimation ); - FILL_ENABLED( file2_song_movie ); - FILL_ENABLED( file2_song_still ); - FILL_ENABLED( file2_global_bganimation ); - FILL_ENABLED( file2_global_movie ); - FILL_ENABLED( file2_global_movie_song_group ); - FILL_ENABLED( file2_global_movie_song_group_and_genre ); + FILL_ENABLED( transition ); + FILL_ENABLED( effect ); + FILL_ENABLED( file1_song_bganimation ); + FILL_ENABLED( file1_song_movie ); + FILL_ENABLED( file1_song_still ); + FILL_ENABLED( file1_global_bganimation ); + FILL_ENABLED( file1_global_movie ); + FILL_ENABLED( file1_global_movie_song_group ); + FILL_ENABLED( file1_global_movie_song_group_and_genre ); + FILL_ENABLED( file2_song_bganimation ); + FILL_ENABLED( file2_song_movie ); + FILL_ENABLED( file2_song_still ); + FILL_ENABLED( file2_global_bganimation ); + FILL_ENABLED( file2_global_movie ); + FILL_ENABLED( file2_global_movie_song_group ); + FILL_ENABLED( file2_global_movie_song_group_and_genre ); #undef FILL_ENABLED - menu.rows[delete_change].bEnabled = bAlreadyBGChangeHere; + menu.rows[delete_change].bEnabled = bAlreadyBGChangeHere; - // set default choices - menu.rows[rate]. SetDefaultChoiceIfPresent( ssprintf("%2.0f%%",bgChange.m_fRate*100) ); - menu.rows[transition]. SetDefaultChoiceIfPresent( bgChange.m_sTransition ); - menu.rows[effect]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sEffect ); - menu.rows[file1_type].iDefaultChoice = none; - if( bgChange.m_def.m_sFile1 == RANDOM_BACKGROUND_FILE ) menu.rows[file1_type].iDefaultChoice = dynamic_random; - if( menu.rows[file1_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_bganimation; - if( menu.rows[file1_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_movie; - if( menu.rows[file1_song_still]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_bitmap; - if( menu.rows[file1_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_bganimation; - if( menu.rows[file1_global_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie; - if( menu.rows[file1_global_movie_song_group]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie_song_group; - if( menu.rows[file1_global_movie_song_group_and_genre]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie_song_group_and_genre; - menu.rows[file2_type].iDefaultChoice = none; - if( bgChange.m_def.m_sFile2 == RANDOM_BACKGROUND_FILE ) menu.rows[file2_type].iDefaultChoice = dynamic_random; - if( menu.rows[file2_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_bganimation; - if( menu.rows[file2_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_movie; - if( menu.rows[file2_song_still]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_bitmap; - if( menu.rows[file2_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_bganimation; - if( menu.rows[file2_global_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie; - if( menu.rows[file2_global_movie_song_group]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie_song_group; - if( menu.rows[file2_global_movie_song_group_and_genre]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie_song_group_and_genre; - menu.rows[color1]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sColor1 ); - menu.rows[color2]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sColor2 ); + // set default choices + menu.rows[rate]. SetDefaultChoiceIfPresent( ssprintf("%2.0f%%",bgChange.m_fRate*100) ); + menu.rows[transition]. SetDefaultChoiceIfPresent( bgChange.m_sTransition ); + menu.rows[effect]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sEffect ); + menu.rows[file1_type].iDefaultChoice = none; + if( bgChange.m_def.m_sFile1 == RANDOM_BACKGROUND_FILE ) menu.rows[file1_type].iDefaultChoice = dynamic_random; + if( menu.rows[file1_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_bganimation; + if( menu.rows[file1_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_movie; + if( menu.rows[file1_song_still]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = song_bitmap; + if( menu.rows[file1_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_bganimation; + if( menu.rows[file1_global_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie; + if( menu.rows[file1_global_movie_song_group]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie_song_group; + if( menu.rows[file1_global_movie_song_group_and_genre]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile1 ) ) menu.rows[file1_type].iDefaultChoice = global_movie_song_group_and_genre; + menu.rows[file2_type].iDefaultChoice = none; + if( bgChange.m_def.m_sFile2 == RANDOM_BACKGROUND_FILE ) menu.rows[file2_type].iDefaultChoice = dynamic_random; + if( menu.rows[file2_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_bganimation; + if( menu.rows[file2_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_movie; + if( menu.rows[file2_song_still]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = song_bitmap; + if( menu.rows[file2_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_bganimation; + if( menu.rows[file2_global_movie]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie; + if( menu.rows[file2_global_movie_song_group]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie_song_group; + if( menu.rows[file2_global_movie_song_group_and_genre]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sFile2 ) ) menu.rows[file2_type].iDefaultChoice = global_movie_song_group_and_genre; + menu.rows[color1]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sColor1 ); + menu.rows[color2]. SetDefaultChoiceIfPresent( bgChange.m_def.m_sColor2 ); - EditMiniMenu( &g_BackgroundChange, SM_BackFromBGChange ); + EditMiniMenu( &g_BackgroundChange, SM_BackFromBGChange ); + } } break; @@ -2718,7 +2721,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if ( SM == SM_BackFromLabelChange ) { RString sLabel = ScreenTextEntry::s_sLastAnswer; - if ( !m_pSteps->m_Timing.DoesLabelExist(sLabel) ) + if ( !GetAppropriateTiming().DoesLabelExist(sLabel) ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); From 123f3a64ed80800b9a90599407cef6873be6e6f7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:03:41 -0400 Subject: [PATCH 118/333] [splittiming] Minor typo. --- Themes/_fallback/metrics.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 9423e563fb..0ab21a76f5 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3627,7 +3627,7 @@ NumHandsFormat="%s: %d\n" NumRollsFormat="%s: %d\n" NumLiftsFormat="%s: %d\n" NumFakesFormat="%s: %d\n" -TimingModeFormat="%:\n %s\n" +TimingModeFormat="%s:\n %s\n" Beat0OffsetFormat="%s:\n %.5f secs\n" PreviewStartFormat="%s:\n %.5f secs\n" PreviewLengthFormat="%s:\n %.5f secs\n" From 4c063eaefd75436fa558d4e0797a954a2209f2a2 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:05:31 -0400 Subject: [PATCH 119/333] [splittiming] Only display needed values. NOTE: Hackish code in here. Improvements would be appreciated. --- src/ScreenEdit.cpp | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 7c738bac1e..5e32eae172 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -562,10 +562,10 @@ static MenuDef g_SongInformation( MenuRowDef( ScreenEdit::max_bpm, "Max BPM", true, EditMode_Full, true, true, 0, NULL ) ); -static MenuDef g_TimingDataInformation( - "ScreenMiniMenuTimingDataInformation", - MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), +static const MenuRowDef g_TimingDataLines[] = +{ + MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::stop, "Edit stop", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), @@ -573,7 +573,12 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ), +}; + +static MenuDef g_TimingDataInformation( + "ScreenMiniMenuTimingDataInformation" + // fill this in dynamically too. ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -3106,6 +3111,21 @@ TimingData & ScreenEdit::GetAppropriateTiming() const void ScreenEdit::DisplayTimingMenu() { + g_TimingDataInformation.rows.clear(); + + for( unsigned i=0; im_bIsEditorStepTiming ) + { + continue; + } + + g_TimingDataInformation.rows.push_back(hl); + } + float fBeat; TimingData &pTime = GetAppropriateTiming(); if( !GAMESTATE->m_bIsEditorStepTiming ) @@ -3116,6 +3136,10 @@ void ScreenEdit::DisplayTimingMenu() { fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; } + + // TODO: Better way of guaranteeing that we don't go out of bounds between timings. + int posLabel = ScreenEdit::tickcount; + int posWarp = ScreenEdit::combo; g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); @@ -3123,13 +3147,16 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); + if( GAMESTATE->m_bIsEditorStepTiming ) { g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + posLabel = ScreenEdit::label; + posWarp = ScreenEdit::warp; } - g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); - g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[posLabel].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); + g_TimingDataInformation.rows[posWarp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } From ba65be23352011737402c7ecbb3ab019c117ca92 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:40:10 -0400 Subject: [PATCH 120/333] [splittiming] Don't show routine key on non. Hmm...does mercurial offer a cherry pick command? --- src/ScreenEdit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 5e32eae172..0a6e8a2a4a 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -4328,6 +4328,13 @@ void ScreenEdit::DoHelp() RString sButtons = GetDeviceButtonsLocalized( hl.veb, m_EditMappingsDeviceInput ); RString sDescription = THEME->GetString( "EditHelpDescription", hl.szEnglishDescription ); + + // TODO: Better way of hiding routine only key on non-routine. + if( sDescription.Left(13) == "Switch player" && m_InputPlayerNumber == PLAYER_INVALID ) + { + continue; + } + g_EditHelp.rows.push_back( MenuRowDef( -1, sDescription, false, EditMode_Practice, false, false, 0, sButtons ) ); } From f9a25062f6d0b5181c2ce402716052c2136558ad Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:40:10 -0400 Subject: [PATCH 121/333] [splittiming] Don't show routine key on non. Hmm...does mercurial offer a cherry pick command? --- src/ScreenEdit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 617d0140b5..0c87f457f8 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -4227,6 +4227,13 @@ void ScreenEdit::DoHelp() RString sButtons = GetDeviceButtonsLocalized( hl.veb, m_EditMappingsDeviceInput ); RString sDescription = THEME->GetString( "EditHelpDescription", hl.szEnglishDescription ); + + // TODO: Better way of hiding routine only key on non-routine. + if( sDescription.Left(13) == "Switch player" && m_InputPlayerNumber == PLAYER_INVALID ) + { + continue; + } + g_EditHelp.rows.push_back( MenuRowDef( -1, sDescription, false, EditMode_Practice, false, false, 0, sButtons ) ); } From 172c80204f331037bcf9f3120706f7078e5908eb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:49:59 -0400 Subject: [PATCH 122/333] [splittiming] doxygen test with transplanting. --- src/ScreenEdit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index eb36e539e2..f76c56a020 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -71,8 +71,8 @@ enum EditButton EDIT_BUTTON_SCROLL_NEXT, EDIT_BUTTON_SCROLL_PREV, - EDIT_BUTTON_LABEL_NEXT, - EDIT_BUTTON_LABEL_PREV, + EDIT_BUTTON_LABEL_NEXT, /**< Jump to the start of the next label downward. */ + EDIT_BUTTON_LABEL_PREV, /**< Jump to the start of the previous label upward. */ // These are modifiers to EDIT_BUTTON_SCROLL_*. EDIT_BUTTON_SCROLL_SELECT, From c33b400c9380ed24240c3e81d0d240fecceab306 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 00:49:59 -0400 Subject: [PATCH 123/333] Transplant latest doxygen from [splittiming]. --- src/ScreenEdit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index ea10ca22a2..4de415230b 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -71,8 +71,8 @@ enum EditButton EDIT_BUTTON_SCROLL_NEXT, EDIT_BUTTON_SCROLL_PREV, - EDIT_BUTTON_LABEL_NEXT, - EDIT_BUTTON_LABEL_PREV, + EDIT_BUTTON_LABEL_NEXT, /**< Jump to the start of the next label downward. */ + EDIT_BUTTON_LABEL_PREV, /**< Jump to the start of the previous label upward. */ // These are modifiers to EDIT_BUTTON_SCROLL_*. EDIT_BUTTON_SCROLL_SELECT, From 2116525e24aa42ec2b2c0bb58459828d3d4e93f7 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Fri, 13 May 2011 14:14:57 +0700 Subject: [PATCH 124/333] [splittiming] display song timing in song timing editing mode (buggy) --- src/NoteField.cpp | 53 ++++++++++++++++++++++++------- src/NoteField.h | 4 ++- src/ScreenEdit.cpp | 78 +++++++++++++++++++++++++++------------------- src/ScreenEdit.h | 3 ++ 4 files changed, 93 insertions(+), 45 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 66cdf2a34b..314da4376c 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -32,6 +32,33 @@ static ThemeMetric FADE_FAIL_TIME( "NoteField", "FadeFailTime" ); static RString RoutineNoteSkinName( size_t i ) { return ssprintf("RoutineNoteSkinP%i",int(i+1)); } static ThemeMetric1D ROUTINE_NOTESKIN( "NoteField", RoutineNoteSkinName, NUM_PLAYERS ); + +inline const TimingData *GetRealTiming(const PlayerState *pPlayerState) +{ + if( GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber] != NULL ) + return &GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing; + return NULL; +} + +inline const TimingData *GetDisplayedTiming(const PlayerState *pPlayerState) +{ + if( !GAMESTATE->m_bIsEditorStepTiming ) + return &GAMESTATE->m_pCurSong->m_SongTiming; + return GetRealTiming(pPlayerState); +} + +inline const SongPosition *GetRealPosition(const PlayerState *pPlayerState) +{ + return &pPlayerState->m_Position; +} + +inline const SongPosition *GetDisplayedPosition(const PlayerState *pPlayerState) +{ + if( !GAMESTATE->m_bIsEditorStepTiming ) + return &GAMESTATE->m_Position; + return GetRealPosition(pPlayerState); +} + NoteField::NoteField() { m_pNoteData = NULL; @@ -240,7 +267,7 @@ void NoteField::Update( float fDeltaTime ) ActorFrame::Update( fDeltaTime ); // update m_fBoardOffsetPixels, m_fCurrentBeatLastUpdate, m_fYPosCurrentBeatLastUpdate - const float fCurrentBeat = m_pPlayerState->m_Position.m_fSongBeat; + const float fCurrentBeat = GetDisplayedPosition(m_pPlayerState)->m_fSongBeat; bool bTweeningOn = m_sprBoard->GetCurrentDiffuseAlpha() >= 0.98 && m_sprBoard->GetCurrentDiffuseAlpha() < 1.00; // HACK if( !bTweeningOn && m_fCurrentBeatLastUpdate != -1 ) { @@ -444,6 +471,7 @@ static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); static ThemeMetric LABEL_OFFSETX ( "NoteField", "LabelOffsetX" ); + void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); @@ -606,7 +634,7 @@ void NoteField::DrawBGChangeText( const float fBeat, const RString sNewBGName ) // change this probing to binary search float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceAfterTargetsPixels ) { - float fFirstBeatToDraw = pPlayerState->m_Position.m_fSongBeat-4; // Adjust to balance off performance and showing enough notes. + float fFirstBeatToDraw = GetDisplayedPosition(pPlayerState)->m_fSongBeat-4; // Adjust to balance off performance and showing enough notes. /* In Boomerang, we'll usually have two sections of notes: before and after * the peak. We always start drawing before the peak, and end after it, or @@ -618,7 +646,7 @@ float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistance bBoomerang = (fAccels[PlayerOptions::ACCEL_BOOMERANG] != 0); } - while( fFirstBeatToDraw < pPlayerState->m_Position.m_fSongBeat ) + while( fFirstBeatToDraw < GetDisplayedPosition(pPlayerState)->m_fSongBeat ) { bool bIsPastPeakYOffset; float fPeakYOffset; @@ -640,7 +668,7 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB // Probe for last note to draw. Worst case is 0.25x + boost. // Adjust search distance so that notes don't pop onto the screen. float fSearchDistance = 10; - float fLastBeatToDraw = pPlayerState->m_Position.m_fSongBeat+fSearchDistance; + float fLastBeatToDraw = GetDisplayedPosition(pPlayerState)->m_fSongBeat+fSearchDistance; const int NUM_ITERATIONS = 20; @@ -739,12 +767,13 @@ void NoteField::DrawPrimitives() cur->m_ReceptorArrowRow.Draw(); } - Steps *stepChecking = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]; + const TimingData *pTiming = GetDisplayedTiming(m_pPlayerState); // Draw beat bars - if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && stepChecking != NULL ) + if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && pTiming != NULL ) { - const vector &vTimeSignatureSegments = stepChecking->m_Timing.m_vTimeSignatureSegments; + const TimingData &timing = *pTiming; + const vector &vTimeSignatureSegments = timing.m_vTimeSignatureSegments; int iMeasureIndex = 0; FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter ) { @@ -783,11 +812,11 @@ void NoteField::DrawPrimitives() } } - if( GAMESTATE->IsEditing() && stepChecking != NULL ) + if( GAMESTATE->IsEditing() && pTiming != NULL ) { ASSERT(GAMESTATE->m_pCurSong); - const TimingData &timing = stepChecking->m_Timing; + const TimingData &timing = *pTiming; // BPM text FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg ) @@ -1056,7 +1085,7 @@ void NoteField::DrawPrimitives() displayCols->display[c].DrawHold( tn, c, iStartRow, bIsHoldingNote, Result, bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, m_fYReverseOffsetPixels, (float) iDrawDistanceAfterTargetsPixels, (float) iDrawDistanceBeforeTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT ); - bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > m_pPlayerState->m_Position.m_fSongBeat; + bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > GetDisplayedPosition(m_pPlayerState)->m_fSongBeat; bAnyUpcomingInThisCol |= bNoteIsUpcoming; } } @@ -1098,7 +1127,7 @@ void NoteField::DrawPrimitives() continue; // skip ASSERT_M( NoteRowToBeat(q) > -2000, ssprintf("%i %i %i, %f %f", q, iLastRowToDraw, - iFirstRowToDraw, m_pPlayerState->m_Position.m_fSongBeat, m_pPlayerState->m_Position.m_fMusicSeconds) ); + iFirstRowToDraw, GetDisplayedPosition(m_pPlayerState)->m_fSongBeat, GetDisplayedPosition(m_pPlayerState)->m_fMusicSeconds) ); // See if there is a hold step that begins on this index. // Only do this if the noteskin cares. @@ -1128,7 +1157,7 @@ void NoteField::DrawPrimitives() m_fYReverseOffsetPixels, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT ); - bool bNoteIsUpcoming = NoteRowToBeat(q) > m_pPlayerState->m_Position.m_fSongBeat; + bool bNoteIsUpcoming = NoteRowToBeat(q) > GetDisplayedPosition(m_pPlayerState)->m_fSongBeat; bAnyUpcomingInThisCol |= bNoteIsUpcoming; } diff --git a/src/NoteField.h b/src/NoteField.h index 560f3cb563..c389676cfb 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -1,6 +1,8 @@ #ifndef NOTE_FIELD_H #define NOTE_FIELD_H +#include "TimingData.h" +#include "SongPosition.h" #include "Sprite.h" #include "ActorFrame.h" #include "BitmapText.h" @@ -65,7 +67,7 @@ protected: void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; - + const NoteData *m_pNoteData; float m_fPercentFadeToFail; // -1 if not fading to fail diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0a6e8a2a4a..8a69a67040 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -735,10 +735,8 @@ void ScreenEdit::Init() GAMESTATE->m_bGameplayLeadIn.Set( true ); GAMESTATE->m_EditMode = EDIT_MODE.GetValue(); - GAMESTATE->m_Position.m_fSongBeat = 0; - FOREACH_PlayerNumber( p ) - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = 0; - m_fTrailingBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + SetBeat(0); + m_fTrailingBeat = 0; m_iShiftAnchor = -1; m_iStartPlayingAt = -1; @@ -1179,9 +1177,13 @@ void ScreenEdit::DrawPrimitives() // HACK: Draw using the trailing beat PlayerState *pPlayerState = const_cast (m_NoteFieldEdit.GetPlayerState()); - float fSongBeat = pPlayerState->m_Position.m_fSongBeat; // save song beat - float fSongBeatNoOffset = pPlayerState->m_Position.m_fSongBeatNoOffset; - float fSongBeatVisible = pPlayerState->m_Position.m_fSongBeatVisible; + float fPlayerSongBeat = pPlayerState->m_Position.m_fSongBeat; // save song beat + float fPlayerSongBeatNoOffset = pPlayerState->m_Position.m_fSongBeatNoOffset; + float fPlayerSongBeatVisible = pPlayerState->m_Position.m_fSongBeatVisible; + + float fGameSongBeat = GAMESTATE->m_Position.m_fSongBeat; // save song beat + float fGameSongBeatNoOffset = GAMESTATE->m_Position.m_fSongBeatNoOffset; + float fGameSongBeatVisible = GAMESTATE->m_Position.m_fSongBeatVisible; pPlayerState->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect pPlayerState->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect @@ -1189,9 +1191,13 @@ void ScreenEdit::DrawPrimitives() ScreenWithMenuElements::DrawPrimitives(); - pPlayerState->m_Position.m_fSongBeat = fSongBeat; // restore real song beat - pPlayerState->m_Position.m_fSongBeatNoOffset = fSongBeatNoOffset; - pPlayerState->m_Position.m_fSongBeatVisible = fSongBeatVisible; + pPlayerState->m_Position.m_fSongBeat = fPlayerSongBeat; // restore real song beat + pPlayerState->m_Position.m_fSongBeatNoOffset = fPlayerSongBeatNoOffset; + pPlayerState->m_Position.m_fSongBeatVisible = fPlayerSongBeatVisible; + + GAMESTATE->m_Position.m_fSongBeat = fGameSongBeat; // restore real song beat + GAMESTATE->m_Position.m_fSongBeatNoOffset = fGameSongBeatNoOffset; + GAMESTATE->m_Position.m_fSongBeatVisible = fGameSongBeatVisible; } @@ -2407,15 +2413,8 @@ void ScreenEdit::TransitionEditState( EditState em ) m_Background.Unload(); m_Foreground.Unload(); - // Restore the cursor position. - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fBeatToReturnTo; - - // Make sure we're snapped. - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = Quantize( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); - - /* Playing and recording have lead-ins, which may start before beat 0; - * make sure we don't stay there if we escaped out early. */ - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = max( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, 0 ); + // Restore the cursor position + Quantize + Clamp + SetBeat( max( 0, Quantize( m_fBeatToReturnTo, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ) ) ); break; @@ -2532,7 +2531,7 @@ void ScreenEdit::ScrollTo( float fDestinationBeat ) if( fOriginalBeat == fDestinationBeat ) return; - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = fDestinationBeat; + SetBeat(fDestinationBeat); // check to see if they're holding a button for( int n=0; nm_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_fTrailingBeat; + SetBeat(m_fTrailingBeat); } else if( SM == SM_LoseFocus ) { @@ -2981,10 +2980,10 @@ void ScreenEdit::OnSnapModeChange() m_soundChangeSnap.Play(); NoteType nt = m_SnapDisplay.GetNoteType(); - int iStepIndex = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + int iStepIndex = BeatToNoteRow( GetBeat() ); int iElementsPerNoteType = BeatToNoteRow( NoteTypeToBeat(nt) ); int iStepIndexHangover = iStepIndex % iElementsPerNoteType; - GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat -= NoteRowToBeat( iStepIndexHangover ); + SetBeat( GetBeat() - NoteRowToBeat( iStepIndexHangover ) ); } @@ -3109,6 +3108,29 @@ TimingData & ScreenEdit::GetAppropriateTiming() const return m_pSong->m_SongTiming; } +inline void ScreenEdit::SetBeat(float fBeat) +{ + if( !GAMESTATE->m_bIsEditorStepTiming ) + { + GAMESTATE->m_Position.m_fSongBeat = fBeat; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_pSteps->m_Timing.GetBeatFromElapsedTime(m_pSong->m_SongTiming.GetElapsedTimeFromBeat(fBeat)); + } + else + { + GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = fBeat; + GAMESTATE->m_Position.m_fSongBeat = m_pSong->m_SongTiming.GetBeatFromElapsedTime(m_pSteps->m_Timing.GetElapsedTimeFromBeat(fBeat)); + } +} + +inline float ScreenEdit::GetBeat() +{ + if( !GAMESTATE->m_bIsEditorStepTiming ) + { + return GAMESTATE->m_Position.m_fSongBeat; + } + return GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; +} + void ScreenEdit::DisplayTimingMenu() { g_TimingDataInformation.rows.clear(); @@ -3126,16 +3148,8 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows.push_back(hl); } - float fBeat; + float fBeat = GetBeat(); TimingData &pTime = GetAppropriateTiming(); - if( !GAMESTATE->m_bIsEditorStepTiming ) - { - fBeat = GAMESTATE->m_Position.m_fSongBeat; - } - else - { - fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; - } // TODO: Better way of guaranteeing that we don't go out of bounds between timings. int posLabel = ScreenEdit::tickcount; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index f76c56a020..da134f6aa2 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -555,6 +555,9 @@ private: * @brief Retrieve the appropriate TimingData based on GAMESTATE. * @return the proper TimingData. */ TimingData & GetAppropriateTiming() const; + void SetBeat(float fBeat); + float GetBeat(); + }; #endif From 1c4b21b18113524687642958478a8783cd9329d0 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Fri, 13 May 2011 15:19:42 +0700 Subject: [PATCH 125/333] [splittiming] ok, now it displays properly. --- src/ArrowEffects.cpp | 10 ++++++---- src/NoteField.cpp | 19 ++++++++++++++++--- src/ScreenEdit.cpp | 18 +++++++++++------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index f5ea953136..a0566826d1 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -85,13 +85,14 @@ void ArrowEffects::Update() FOREACH_PlayerNumber( pn ) { const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; + const SongPosition &position = GAMESTATE->m_bIsEditorStepTiming ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; PerPlayerData &data = g_EffectData[pn]; { static float fLastTime = 0; float fTime = RageTimer::GetTimeSinceStartFast(); - if( !GAMESTATE->m_pPlayerState[pn]->m_Position.m_bFreeze || !GAMESTATE->m_pPlayerState[pn]->m_Position.m_bDelay ) + if( !position.m_bFreeze || !position.m_bDelay ) { data.m_fExpandSeconds += fTime - fLastTime; data.m_fExpandSeconds = fmodf( data.m_fExpandSeconds, PI*2 ); @@ -177,7 +178,7 @@ void ArrowEffects::Update() // Update Beat do { float fAccelTime = 0.2f, fTotalTime = 0.5f; - float fBeat = GAMESTATE->m_pPlayerState[pn]->m_Position.m_fSongBeatVisible + fAccelTime; + float fBeat = position.m_fSongBeatVisible + fAccelTime; const bool bEvenBeat = ( int(fBeat) % 2 ) != 0; @@ -218,12 +219,13 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float bIsPastPeakOut = true; float fYOffset = 0; + const SongPosition &position = GAMESTATE->m_bIsEditorStepTiming ? pPlayerState->m_Position : GAMESTATE->m_Position; /* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or * entirely time spacing (respectively). Occasionally, we tween between them. */ if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 1.0f ) { - float fSongBeat = pPlayerState->m_Position.m_fSongBeatVisible; + float fSongBeat = position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); @@ -231,7 +233,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) { - float fSongSeconds = pPlayerState->m_Position.m_fMusicSecondsVisible; + float fSongSeconds = position.m_fMusicSecondsVisible; float fNoteSeconds = GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 314da4376c..6982277071 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -697,6 +697,19 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB return fLastBeatToDraw; } +inline float NoteRowToVisibleBeat( const PlayerState *pPlayerState, int iRow ) +{ + /* + if( GAMESTATE->m_bIsEditorStepTiming ) + { + */ + return NoteRowToBeat(iRow); + /* + } + return GetDisplayedTiming(pPlayerState)->GetBeatFromElapsedTime(GetRealTiming(pPlayerState)->GetElapsedTimeFromBeat(NoteRowToBeat(iRow))); + */ +} + bool NoteField::IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const { // TRICKY: If boomerang is on, then ones in the range @@ -1054,8 +1067,8 @@ void NoteField::DrawPrimitives() float fThrowAway; bool bStartIsPastPeak = false; bool bEndIsPastPeak = false; - float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iStartRow), fThrowAway, bStartIsPastPeak ); - float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(iEndRow), fThrowAway, bEndIsPastPeak ); + float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iStartRow), fThrowAway, bStartIsPastPeak ); + float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iEndRow), fThrowAway, bEndIsPastPeak ); bool bTailIsOnVisible = iDrawDistanceAfterTargetsPixels <= fEndYOffset && fEndYOffset <= iDrawDistanceBeforeTargetsPixels; bool bHeadIsVisible = iDrawDistanceAfterTargetsPixels <= fStartYOffset && fStartYOffset <= iDrawDistanceBeforeTargetsPixels; @@ -1152,7 +1165,7 @@ void NoteField::DrawPrimitives() bool bIsHopoPossible = (tn.bHopoPossible); bool bUseAdditionColoring = bIsAddition || bIsHopoPossible; NoteDisplayCols *displayCols = tn.pn == PLAYER_INVALID ? m_pCurDisplay : m_pDisplays[tn.pn]; - displayCols->display[c].DrawTap( tn, c, NoteRowToBeat(q), bHoldNoteBeginsOnThisBeat, + displayCols->display[c].DrawTap( tn, c, NoteRowToVisibleBeat(m_pPlayerState, q), bHoldNoteBeginsOnThisBeat, bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail, m_fYReverseOffsetPixels, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT ); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8a69a67040..94a2bb44f1 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1010,12 +1010,12 @@ void ScreenEdit::Update( float fDeltaTime ) // Update trailing beat - float fDelta = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat - m_fTrailingBeat; + float fDelta = GetBeat() - m_fTrailingBeat; if( fabsf(fDelta) < 10 ) - fapproach( m_fTrailingBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, + fapproach( m_fTrailingBeat, GetBeat(), fDeltaTime*40 / m_NoteFieldEdit.GetPlayerState()->m_PlayerOptions.GetCurrent().m_fScrollSpeed ); else - fapproach( m_fTrailingBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, + fapproach( m_fTrailingBeat, GetBeat(), fabsf(fDelta) * fDeltaTime*5 ); PlayTicks(); @@ -1090,8 +1090,8 @@ void ScreenEdit::UpdateTextInfo() RString sNoteType = ssprintf( NOTES.GetValue(), NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType()).c_str() ); RString sText; - sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); - sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ); + sText += ssprintf( CURRENT_BEAT_FORMAT.GetValue(), CURRENT_BEAT.GetValue().c_str(), GetBeat() ); + sText += ssprintf( CURRENT_SECOND_FORMAT.GetValue(), CURRENT_SECOND.GetValue().c_str(), GetAppropriateTiming().GetElapsedTimeFromBeat(GetBeat()) ); switch( EDIT_MODE.GetValue() ) { DEFAULT_FAIL( EDIT_MODE.GetValue() ); @@ -1188,6 +1188,10 @@ void ScreenEdit::DrawPrimitives() pPlayerState->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect pPlayerState->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect pPlayerState->m_Position.m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect + + GAMESTATE->m_Position.m_fSongBeat = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_Position.m_fSongBeatNoOffset = m_fTrailingBeat; // put trailing beat in effect + GAMESTATE->m_Position.m_fSongBeatVisible = m_fTrailingBeat; // put trailing beat in effect ScreenWithMenuElements::DrawPrimitives(); @@ -1446,7 +1450,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( m_PlayerStateEdit.m_PlayerOptions.GetSong().m_fScrolls[PlayerOptions::SCROLL_REVERSE] > 0.5 ) fBeatsToMove *= -1; - float fDestinationBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat + fBeatsToMove; + float fDestinationBeat = GetBeat() + fBeatsToMove; fDestinationBeat = Quantize( fDestinationBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); ScrollTo( fDestinationBeat ); @@ -2969,7 +2973,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if( SM == SM_LoseFocus ) { // Snap the trailing beat, in case we lose focus while tweening. - m_fTrailingBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + m_fTrailingBeat = GetBeat(); //GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; } ScreenWithMenuElements::HandleScreenMessage( SM ); From f694fe5955556b09d6eb7677548a34ea3128f844 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 08:50:59 -0400 Subject: [PATCH 126/333] [splittiming] Add sounds to recent actions. --- Themes/_fallback/Sounds/ScreenEdit switch player.redir | 1 + Themes/_fallback/Sounds/ScreenEdit switch timing.redir | 1 + src/ScreenEdit.cpp | 4 ++++ src/ScreenEdit.h | 8 ++++++++ 4 files changed, 14 insertions(+) create mode 100644 Themes/_fallback/Sounds/ScreenEdit switch player.redir create mode 100644 Themes/_fallback/Sounds/ScreenEdit switch timing.redir diff --git a/Themes/_fallback/Sounds/ScreenEdit switch player.redir b/Themes/_fallback/Sounds/ScreenEdit switch player.redir new file mode 100644 index 0000000000..cd59d419fb --- /dev/null +++ b/Themes/_fallback/Sounds/ScreenEdit switch player.redir @@ -0,0 +1 @@ +MusicWheel sort diff --git a/Themes/_fallback/Sounds/ScreenEdit switch timing.redir b/Themes/_fallback/Sounds/ScreenEdit switch timing.redir new file mode 100644 index 0000000000..cd59d419fb --- /dev/null +++ b/Themes/_fallback/Sounds/ScreenEdit switch timing.redir @@ -0,0 +1 @@ +MusicWheel sort diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 94a2bb44f1..35760b7872 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -837,6 +837,8 @@ void ScreenEdit::Init() m_soundMarker.Load( THEME->GetPathS("ScreenEdit","marker"), true ); m_soundValueIncrease.Load( THEME->GetPathS("ScreenEdit","value increase"), true ); m_soundValueDecrease.Load( THEME->GetPathS("ScreenEdit","value decrease"), true ); + m_soundSwitchPlayer.Load( THEME->GetPathS("ScreenEdit","switch player"), true ); + m_soundSwitchTiming.Load( THEME->GetPathS("ScreenEdit","switch timing"), true ); m_soundSwitchSteps.Load( THEME->GetPathS("ScreenEdit","switch steps") ); m_soundSave.Load( THEME->GetPathS("ScreenEdit","save") ); m_GameplayAssist.Init(); @@ -2124,11 +2126,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) enum_add( m_InputPlayerNumber, 1 ); if( m_InputPlayerNumber == NUM_PLAYERS ) m_InputPlayerNumber = PLAYER_1; + m_soundSwitchPlayer.Play(); } break; case EDIT_BUTTON_SWITCH_TIMINGS: GAMESTATE->m_bIsEditorStepTiming = !GAMESTATE->m_bIsEditorStepTiming; + m_soundSwitchTiming.Play(); break; } } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index da134f6aa2..d6a472e5c3 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -281,14 +281,22 @@ protected: /** @brief Has the NoteData been changed such that a user should be prompted to save? */ bool m_bDirty; + /** @brief The sound that is played when a note is added. */ RageSound m_soundAddNote; + /** @brief The sound that is played when a note is removed. */ RageSound m_soundRemoveNote; RageSound m_soundChangeLine; RageSound m_soundChangeSnap; RageSound m_soundMarker; RageSound m_soundValueIncrease; RageSound m_soundValueDecrease; + /** @brief The sound that is played when switching players for Routine. */ + RageSound m_soundSwitchPlayer; + /** @brief The sound that is played when switching song/step timing. */ + RageSound m_soundSwitchTiming; + /** @brief The sound that is played when switching to a different chart. */ RageSound m_soundSwitchSteps; + /** @brief The sound that is played when the chart is saved. */ RageSound m_soundSave; // used for reverting From b43dabc0948d8f6b558fc0f14dac95e7d6a61d73 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:05:32 -0400 Subject: [PATCH 127/333] [splittiming] Tap insertions are Step Time only. --- src/ScreenEdit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 35760b7872..0b8f28af26 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1306,6 +1306,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( input.type != IET_FIRST_PRESS ) break; // We only care about first presses + + if( !GAMESTATE->m_bIsEditorStepTiming ) + { + // TODO: broadcast a message...? + break; // Only allow steps to be hit in Step Timing. + } + int iCol = EditB - EDIT_BUTTON_COLUMN_0; From a7b58e07a203c286dd1863bc2ef79bbd77037e0b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:20:42 -0400 Subject: [PATCH 128/333] [splittiming] Broadcast message on failure. --- Themes/_fallback/Languages/en.ini | 1 + src/ScreenEdit.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index a2014d3f75..03cef7dd16 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1257,6 +1257,7 @@ This change creates more than %d notes in a measure.=This change creates more th This change creates notes past the end of the music and is not allowed.=This change creates notes past the end of the music and is not allowed. This will destroy all unsaved changes.=This will destroy all unsaved changes. Undo=Undo +You must be in Step Timing Mode to edit the notes.=You must be in Step Timing Mode to edit the notes. Current beat=Current beat Current second=Current second diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0b8f28af26..025decb52b 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1276,9 +1276,10 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime ) return -1; } +static LocalizedString TAP_NOTE_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to edit the notes." ); static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" ); static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" ); -static ThemeMetric INVERT_SCROLL_BUTTONS ( "ScreenEdit", "InvertScrollSpeedButtons" ); +static ThemeMetric INVERT_SCROLL_BUTTONS ( "ScreenEdit", "InvertScrollSpeedButtons" ); void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { @@ -1309,8 +1310,9 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( !GAMESTATE->m_bIsEditorStepTiming ) { - // TODO: broadcast a message...? - break; // Only allow steps to be hit in Step Timing. + // Only allow steps to be hit in Step Timing. + SCREENMAN->SystemMessage( TAP_NOTE_SONG_TIMING ); + break; } int iCol = EditB - EDIT_BUTTON_COLUMN_0; From 6f6c18e0508f3d9f392c79353160590adfe58951 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:44:54 -0400 Subject: [PATCH 129/333] [splittiming] More SST fixes. --- src/ScreenEdit.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 025decb52b..bfc51637a7 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2153,6 +2153,9 @@ void ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB ) TransitionEditState( STATE_EDITING ); return; } + + if ( !GAMESTATE->m_bIsEditorStepTiming ) + return; // can't allow changes if in song timing. if( input.pn != PLAYER_1 ) return; // ignore @@ -3667,16 +3670,16 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns TransitionEditState( STATE_RECORDING ); break; case insert_and_shift: - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) ); break; case delete_and_shift: - NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + NoteDataUtil::DeleteRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) ); break; case shift_pauses_forward: - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + GetAppropriateTiming().InsertRows( BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) ); break; case shift_pauses_backward: - m_pSteps->m_Timing.DeleteRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), BeatToNoteRow(1) ); + GetAppropriateTiming().DeleteRows( BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) ); break; case convert_to_pause: { From cba8011765ab72008ea59dda8f7832badb57e065 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:49:00 -0400 Subject: [PATCH 130/333] [splittiming] Preemptive SST fixing. --- src/ScreenEdit.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index bfc51637a7..775a1f29b5 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3684,8 +3684,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_to_pause: { ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ); - float fMarkerStart = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); - float fMarkerEnd = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); + float fMarkerStart = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); + float fMarkerEnd = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) ); // The length of the stop segment we're going to create. This includes time spent in any // stops in the selection, which will be deleted and subsumed into the new stop. @@ -3697,9 +3697,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns m_NoteFieldEdit.m_iBeginMarker + 1, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSteps->m_Timing.DeleteRows( m_NoteFieldEdit.m_iBeginMarker, + GetAppropriateTiming().DeleteRows( m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker ); - m_pSteps->m_Timing.SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); + GetAppropriateTiming().SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength ); m_NoteFieldEdit.m_iBeginMarker = -1; m_NoteFieldEdit.m_iEndMarker = -1; break; @@ -3707,14 +3707,14 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case convert_pause_to_beat: { // TODO: Convert both Delays and Stops at once. - float fStopSeconds = m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ); - m_pSteps->m_Timing.SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, 0 ); + float fStopSeconds = GetAppropriateTiming().GetStopAtRow( BeatToNoteRow( GetBeat() ) ); + GetAppropriateTiming().SetStopAtBeat( GetBeat() , 0 ); - float fStopBeats = fStopSeconds * m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) / 60; + float fStopBeats = fStopSeconds * GetAppropriateTiming().GetBPMAtBeat( GetBeat() ) / 60; // don't move the step from where it is, just move everything later - NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSteps->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); + NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ) + 1, BeatToNoteRow(fStopBeats) ); + GetAppropriateTiming().InsertRows( BeatToNoteRow( GetBeat() ) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: From 844f5828a55a8a1f90906c5d5b706e2f0b3a1a47 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:53:06 -0400 Subject: [PATCH 131/333] [splittiming] Use SST, Simplify. --- src/ScreenEdit.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 775a1f29b5..6799d93409 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3874,14 +3874,14 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice DEFAULT_FAIL( c ); case beat_0_offset: ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, - ssprintf("%.5f", m_pSteps->m_Timing.m_fBeat0OffsetInSeconds), 20, + ssprintf("%.5f", GetAppropriateTiming().m_fBeat0OffsetInSeconds), 20, ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); break; case bpm: ScreenTextEntry::TextEntry( SM_BackFromBPMChange, ENTER_BPM_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetBPMAtBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ), + ssprintf( "%.4f", GetAppropriateTiming().GetBPMAtBeat( GetBeat() ) ), 10 ); break; @@ -3889,7 +3889,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromStopChange, ENTER_STOP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetStopAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", GetAppropriateTiming().GetStopAtBeat( GetBeat() ) ), 10 ); break; @@ -3897,7 +3897,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromDelayChange, ENTER_DELAY_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetDelayAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", GetAppropriateTiming().GetDelayAtBeat( GetBeat() ) ), 10 ); break; @@ -3905,7 +3905,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureNumeratorChange, ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator ), + ssprintf( "%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iNumerator ), 3 ); break; @@ -3913,7 +3913,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTimeSignatureDenominatorChange, ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iDenominator ), + ssprintf( "%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iDenominator ), 3 ); break; @@ -3921,7 +3921,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromTickcountChange, ENTER_TICKCOUNT_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ), + ssprintf( "%d", GetAppropriateTiming().GetTickcountAtBeat( GetBeat() ) ), 2 ); break; @@ -3929,7 +3929,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromComboChange, ENTER_COMBO_VALUE, - ssprintf( "%d", m_pSteps->m_Timing.GetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ), + ssprintf( "%d", GetAppropriateTiming().GetComboAtBeat( GetBeat() ) ), 4 ); break; @@ -3937,7 +3937,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromLabelChange, ENTER_LABEL_VALUE, - ssprintf( "%s", m_pSteps->m_Timing.GetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).c_str() ), + ssprintf( "%s", GetAppropriateTiming().GetLabelAtBeat( GetBeat() ).c_str() ), 64 ); break; @@ -3945,7 +3945,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", m_pSteps->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) ), + ssprintf( "%.4f", GetAppropriateTiming().GetWarpAtBeat( GetBeat() ) ), 10 ); break; From af3fb53d182a3a5c93a1cda444685914d742d033 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 09:55:25 -0400 Subject: [PATCH 132/333] [splittiming] doxygen note on SST. --- src/ScreenEdit.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index d6a472e5c3..f783cf5368 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -529,6 +529,12 @@ public: NUM_BGCHANGE_CHOICES }; + /** + * @brief Take care of any background changes that the user wants. + * + * It is important that this is only called in Song Timing mode. + * @param c the Background Change style requested. + * @param iAnswers the other settings involving the change. */ void HandleBGChangeChoice( BGChangeChoice c, const vector &iAnswers ); enum CourseAttackChoice From d85b9552b4153c771b4d0ac1025d7bcb5822305b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 10:07:41 -0400 Subject: [PATCH 133/333] [splittiming] Use more SST functions. --- src/ScreenEdit.cpp | 60 ++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 6799d93409..10adb8c403 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -936,6 +936,8 @@ void ScreenEdit::Update( float fDeltaTime ) if( m_EditState == STATE_RECORDING ) { + // TODO: Find a way to prevent STATE_RECORDING when in Song Timing. + for( int t=0; tGetCurrentStyle()->m_iColsPerPlayer; t++ ) // for each track { GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( t, PLAYER_1 ); @@ -950,7 +952,7 @@ void ScreenEdit::Update( float fDeltaTime ) float fStartedHoldingSeconds = m_pSoundMusic->GetPositionSeconds() - fSecsHeld; float fStartBeat = max( fStartPlayingAtBeat, m_pSteps->m_Timing.GetBeatFromElapsedTime(fStartedHoldingSeconds) ); - float fEndBeat = max( fStartBeat, GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + float fEndBeat = max( fStartBeat, GetBeat() ); fEndBeat = min( fEndBeat, NoteRowToBeat(m_iStopPlayingAt) ); // Round start and end to the nearest snap interval @@ -992,12 +994,13 @@ void ScreenEdit::Update( float fDeltaTime ) } float fLastBeat = NoteRowToBeat(m_iStopPlayingAt); - if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING ) + if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING && GAMESTATE->m_bIsEditorStepTiming ) { float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( fLastBeat ); fLastBeat = m_pSteps->m_Timing.GetBeatFromElapsedTime( fSeconds + 0.5f ); } + // This should be fine: it will convert to the same I believe. -Wolfman2000 float fStopAtSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStopPlayingAt) ) + 1; if( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fMusicSeconds > fStopAtSeconds ) { @@ -1638,7 +1641,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_BPM_UP: case EDIT_BUTTON_BPM_DOWN: { - float fBPM = m_pSteps->m_Timing.GetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + float fBPM = GetAppropriateTiming().GetBPMAtBeat( GetBeat() ); float fDelta; switch( EditB ) { @@ -1659,7 +1662,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } float fNewBPM = fBPM + fDelta; - m_pSteps->m_Timing.SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fNewBPM ); + GetAppropriateTiming().SetBPMAtBeat( GetBeat(), fNewBPM ); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1686,24 +1689,24 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_Timing.m_StopSegments.size(); i++ ) + for( i=0; im_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat) ) + if( GetAppropriateTiming().m_StopSegments[i].m_iStartRow == BeatToNoteRow( GetBeat() ) ) break; } - if( i == m_pSteps->m_Timing.m_StopSegments.size() ) // there is no StopSegment at the current beat + if( i == GetAppropriateTiming().m_StopSegments.size() ) // there is no StopSegment at the current beat { // create a new StopSegment if( fDelta > 0 ) - m_pSteps->m_Timing.AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat), fDelta) ); + GetAppropriateTiming().AddStopSegment( StopSegment(BeatToNoteRow( GetBeat() ), fDelta) ); } else // StopSegment being modified is m_SongTiming.m_StopSegments[i] { - m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSteps->m_Timing.m_StopSegments.erase( m_pSteps->m_Timing.m_StopSegments.begin()+i, - m_pSteps->m_Timing.m_StopSegments.begin()+i+1); + GetAppropriateTiming().m_StopSegments[i].m_fStopSeconds += fDelta; + if( GetAppropriateTiming().m_StopSegments[i].m_fStopSeconds <= 0 ) + GetAppropriateTiming().m_StopSegments.erase( GetAppropriateTiming().m_StopSegments.begin()+i, + GetAppropriateTiming().m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1732,13 +1735,13 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) fDelta *= 40; } unsigned i; - for( i=0; im_Timing.m_StopSegments.size(); i++ ) + for( i=0; im_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) + if( GetAppropriateTiming().m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_Position.m_fSongBeat) ) break; } - if( i == m_pSteps->m_Timing.m_StopSegments.size() ) // there is no delay segment at the current beat + if( i == GetAppropriateTiming().m_StopSegments.size() ) // there is no delay segment at the current beat { // create a new delay segment if( fDelta > 0 ) @@ -1746,10 +1749,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } else // delay segment being modified is m_SongTiming.m_StopSegments[i] { - m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds += fDelta; - if( m_pSteps->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 ) - m_pSteps->m_Timing.m_StopSegments.erase( m_pSteps->m_Timing.m_StopSegments.begin()+i, - m_pSteps->m_Timing.m_StopSegments.begin()+i+1); + GetAppropriateTiming().m_StopSegments[i].m_fStopSeconds += fDelta; + if( GetAppropriateTiming().m_StopSegments[i].m_fStopSeconds <= 0 ) + GetAppropriateTiming().m_StopSegments.erase( GetAppropriateTiming().m_StopSegments.begin()+i, + GetAppropriateTiming().m_StopSegments.begin()+i+1); } (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); @@ -1777,7 +1780,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) else fDelta *= 40; } - m_pSteps->m_Timing.m_fBeat0OffsetInSeconds += fDelta; + GetAppropriateTiming().m_fBeat0OffsetInSeconds += fDelta; (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); SetDirty( true ); } @@ -1958,6 +1961,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU: { + // TODO: Give Song/Step Timing switches/functions here? Course *pCourse = GAMESTATE->m_pCurCourse; if( pCourse == NULL ) break; @@ -2003,6 +2007,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } else { + // TODO: Give Song/Step Timing switches/functions here? fStart = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); int iAttack = FindAttackAtTime( ce.attacks, fStart ); @@ -2336,7 +2341,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB ) fOffsetDelta *= 40; } - m_pSteps->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta; + GetAppropriateTiming().m_fBeat0OffsetInSeconds += fOffsetDelta; } break; } @@ -2444,9 +2449,10 @@ void ScreenEdit::TransitionEditState( EditState em ) if( bStateChanging ) AdjustSync::ResetOriginalSyncData(); - /* Give a 1 second lead-in. If we're loading Player, this must be done first. */ - float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; - GAMESTATE->UpdateSongPosition( fSeconds, m_pSteps->m_Timing, RageZeroTimer, true ); + /* Give a 1 second lead-in. If we're loading Player, this must be done first. + * Also be sure to get the right timing. */ + float fSeconds = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; + GAMESTATE->UpdateSongPosition( fSeconds, GetAppropriateTiming(), RageZeroTimer, true ); GAMESTATE->m_bGameplayLeadIn.Set( false ); @@ -2527,7 +2533,7 @@ void ScreenEdit::TransitionEditState( EditState em ) { case STATE_PLAYING: case STATE_RECORDING: - const float fStartSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat(GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat); + const float fStartSeconds = GetAppropriateTiming().GetElapsedTimeFromBeat( GetBeat() ); LOG->Trace( "Starting playback at %f", fStartSeconds ); RageSoundParams p; @@ -2828,6 +2834,8 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) Course *pCourse = GAMESTATE->m_pCurCourse; CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex]; int iAttack; + + // TODO: Handle Song/Step Timing functions/switches here? g_fLastInsertAttackPositionSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( GAMESTATE->m_Position.m_fSongBeat ); g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] ); @@ -3630,7 +3638,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex ); // scale timing data - m_pSteps->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); + GetAppropriateTiming().ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); // scale all other steps. /* From e26868a2d7ed49d213e41618e9956c804d433aeb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 10:51:09 -0400 Subject: [PATCH 134/333] [splittiming] More SST. --- src/ScreenEdit.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 10adb8c403..c1d721de8c 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1326,7 +1326,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) ShiftToRightSide( iCol, m_NoteDataEdit.GetNumTracks() ); - const float fSongBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + const float fSongBeat = GetBeat(); const int iSongIndex = BeatToNoteRow( fSongBeat ); if( iCol >= m_NoteDataEdit.GetNumTracks() ) // this button is not in the range of columns for this Style @@ -2179,7 +2179,7 @@ void ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB ) } // Add a tap - float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat; + float fBeat = GetBeat(); fBeat = Quantize( fBeat, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ); const int iRow = BeatToNoteRow( fBeat ); @@ -2695,21 +2695,21 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fBPM > 0 ) - GetAppropriateTiming().SetBPMAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fBPM ); + GetAppropriateTiming().SetBPMAtBeat( GetBeat(), fBPM ); SetDirty( true ); } else if( SM == SM_BackFromStopChange ) { float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fStop >= 0 ) - GetAppropriateTiming().SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fStop ); + GetAppropriateTiming().SetStopAtBeat( GetBeat(), fStop ); SetDirty( true ); } else if( SM == SM_BackFromDelayChange ) { float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); if( fDelay >= 0 ) - GetAppropriateTiming().SetStopAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fDelay, true ); + GetAppropriateTiming().SetStopAtBeat( GetBeat(), fDelay, true ); SetDirty( true ); } else if( SM == SM_BackFromTimeSignatureNumeratorChange ) @@ -2717,7 +2717,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iNum > 0 ) { - GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iNum ); + GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GetBeat(), iNum ); } SetDirty( true ); } @@ -2726,7 +2726,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iDen = StringToInt( ScreenTextEntry::s_sLastAnswer ); if( iDen > 0) { - GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iDen ); + GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GetBeat(), iDen ); } SetDirty( true ); } @@ -2735,7 +2735,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) { - GetAppropriateTiming().SetTickcountAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iTick ); + GetAppropriateTiming().SetTickcountAtBeat( GetBeat(), iTick ); } SetDirty( true ); } @@ -2744,7 +2744,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iCombo = StringToInt( ScreenTextEntry::s_sLastAnswer ); if ( iCombo >= 0 ) { - GetAppropriateTiming().SetComboAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, iCombo ); + GetAppropriateTiming().SetComboAtBeat( GetBeat(), iCombo ); } SetDirty( true ); } @@ -2755,14 +2755,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) { sLabel.Replace("=", "_"); sLabel.Replace(",", "_"); - GetAppropriateTiming().SetLabelAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, sLabel ); + GetAppropriateTiming().SetLabelAtBeat( GetBeat(), sLabel ); SetDirty( true ); } } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - GetAppropriateTiming().SetWarpAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, fWarp ); + GetAppropriateTiming().SetWarpAtBeat( GetBeat(), fWarp ); SetDirty( true ); } else if( SM == SM_BackFromBGChange ) @@ -3494,6 +3494,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case paste_at_current_beat: case paste_at_begin_marker: { + // TODO: Song/Step Timing checks? + int iDestFirstRow = -1; switch( c ) { From e3cec47a419f3a67b1889cce1c92840b83283582 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 15:21:48 -0400 Subject: [PATCH 135/333] [splittiming] More SST adjustments. --- src/ScreenEdit.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index c1d721de8c..ed6d0bb541 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1472,42 +1472,40 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_SCROLL_NEXT_MEASURE: { - float fDestinationBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat + beatsPerMeasure; + float fDestinationBeat = GetBeat() + beatsPerMeasure; fDestinationBeat = ftruncf( fDestinationBeat, (float)beatsPerMeasure ); ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_PREV_MEASURE: { - float fDestinationBeat = QuantizeUp( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat, (float)beatsPerMeasure ); + float fDestinationBeat = QuantizeUp( GetBeat(), (float)beatsPerMeasure ); fDestinationBeat -= (float)beatsPerMeasure; ScrollTo( fDestinationBeat ); break; } case EDIT_BUTTON_SCROLL_NEXT: { - int iRow = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + int iRow = BeatToNoteRow( GetBeat() ); NoteDataUtil::GetNextEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } break; case EDIT_BUTTON_SCROLL_PREV: { - int iRow = BeatToNoteRow( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); + int iRow = BeatToNoteRow( GetBeat() ); NoteDataUtil::GetPrevEditorPosition( m_NoteDataEdit, iRow ); ScrollTo( NoteRowToBeat(iRow) ); } break; case EDIT_BUTTON_LABEL_NEXT: { - ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ); + ScrollTo( GetAppropriateTiming().GetNextLabelSegmentBeatAtBeat( GetBeat() ) ); } break; case EDIT_BUTTON_LABEL_PREV: { - ScrollTo( GAMESTATE->m_pCurSong->m_SongTiming. - GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ) ); + ScrollTo( GetAppropriateTiming().GetPreviousLabelSegmentBeatAtBeat( GetBeat() ) ); } break; case EDIT_BUTTON_SNAP_NEXT: From 9e747aa84b7c21f6692f4fa42f57560487754009 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 15:25:19 -0400 Subject: [PATCH 136/333] [splittiming] No longer just pauses and BPMs. --- Themes/_fallback/Languages/en.ini | 4 ++-- src/ScreenEdit.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 03cef7dd16..49bc09f431 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -983,8 +983,8 @@ Set modifiers=Set modifiers Set Mods=Set Mods Set selection start=Set selection start Set selection end=Set selection end -Shift pauses and BPM changes down=Shift pauses and BPM changes down -Shift pauses and BPM changes up=Shift pauses and BPM changes up +Shift all timing changes down=Shift all timing changes down +Shift all timing changes up=Shift all timing changes up ShowBanners=Show Banners ShowBeginnerHelper=Beginner Helper ShowCaution=Caution diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index ed6d0bb541..158250f238 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -516,8 +516,8 @@ static MenuDef g_AreaMenu( MenuRowDef( ScreenEdit::record, "Record in selection", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::insert_and_shift, "Insert beat and shift down", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::delete_and_shift, "Delete beat and shift up", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift pauses and BPM changes down", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift pauses and BPM changes up", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift all timing changes down", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift all timing changes up", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::convert_to_pause, "Convert selection to pause", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::convert_pause_to_beat, "Convert pause to beats", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL ) From 4d9e2417f637decffba816f21d8fd0fd8ca48ac6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 15:25:19 -0400 Subject: [PATCH 137/333] Bring in language update from [splittiming]. --- Themes/_fallback/Languages/en.ini | 4 ++-- src/ScreenEdit.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index d0492d5a94..89502509c8 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -983,8 +983,8 @@ Set modifiers=Set modifiers Set Mods=Set Mods Set selection start=Set selection start Set selection end=Set selection end -Shift pauses and BPM changes down=Shift pauses and BPM changes down -Shift pauses and BPM changes up=Shift pauses and BPM changes up +Shift all timing changes down=Shift all timing changes down +Shift all timing changes up=Shift all timing changes up ShowBanners=Show Banners ShowBeginnerHelper=Beginner Helper ShowCaution=Caution diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0c87f457f8..9d1e462c83 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -510,8 +510,8 @@ static MenuDef g_AreaMenu( MenuRowDef( ScreenEdit::record, "Record in selection", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::insert_and_shift, "Insert beat and shift down", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::delete_and_shift, "Delete beat and shift up", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift pauses and BPM changes down", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift pauses and BPM changes up", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift all timing changes down", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift all timing changes up", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::convert_to_pause, "Convert selection to pause", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::convert_pause_to_beat, "Convert pause to beats", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL ) From e95ac1eef0f743d3e68c873b93ad71a7752c73e3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 15:38:21 -0400 Subject: [PATCH 138/333] [splittiming] Song Timings don't get warps. Song Timing is meant for background changes and emergency fallback Step Timing. Warps do not belong here. --- src/NotesWriterSSC.cpp | 19 +++++++++++-------- src/ScreenEdit.cpp | 8 +++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 445aa9ee5b..3e7882741e 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -82,7 +82,7 @@ struct TimingTagWriter { }; -static void GetTimingTags( vector &lines, TimingData timing ) +static void GetTimingTags( vector &lines, TimingData timing, bool bIsSong = false ) { TimingTagWriter w ( &lines ); @@ -105,10 +105,13 @@ static void GetTimingTags( vector &lines, TimingData timing ) w.Write( ss->m_iStartRow, ss->m_fStopSeconds ); w.Finish(); - w.Init( "WARPS" ); - FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) - w.Write( ws->m_iStartRow, ws->m_fEndBeat ); - w.Finish(); + if( !bIsSong ) + { + w.Init( "WARPS" ); + FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) + w.Write( ws->m_iStartRow, ws->m_fEndBeat ); + w.Finish(); + } ASSERT( !timing.m_vTimeSignatureSegments.empty() ); w.Init( "TIMESIGNATURES" ); @@ -134,12 +137,12 @@ static void GetTimingTags( vector &lines, TimingData timing ) w.Finish(); } -static void WriteTimingTags( RageFile &f, const TimingData &timing ) +static void WriteTimingTags( RageFile &f, const TimingData &timing, bool bIsSong = false ) { vector lines; - GetTimingTags( lines, timing ); + GetTimingTags( lines, timing, bIsSong ); f.PutLine( JoinLineList( lines ) ); @@ -210,7 +213,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) break; } - WriteTimingTags( f, out.m_SongTiming ); + WriteTimingTags( f, out.m_SongTiming, true ); FOREACH_BackgroundLayer( b ) { diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 158250f238..0ff4b95235 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3165,8 +3165,8 @@ void ScreenEdit::DisplayTimingMenu() { const MenuRowDef &hl = g_TimingDataLines[i]; - if( ( hl.iRowCode == ScreenEdit::tickcount || hl.iRowCode == ScreenEdit::combo ) - && !GAMESTATE->m_bIsEditorStepTiming ) + if( ( hl.iRowCode == ScreenEdit::tickcount || hl.iRowCode == ScreenEdit::combo + || hl.iRowCode == ScreenEdit::warp ) && !GAMESTATE->m_bIsEditorStepTiming ) { continue; } @@ -3179,7 +3179,6 @@ void ScreenEdit::DisplayTimingMenu() // TODO: Better way of guaranteeing that we don't go out of bounds between timings. int posLabel = ScreenEdit::tickcount; - int posWarp = ScreenEdit::combo; g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); @@ -3192,11 +3191,10 @@ void ScreenEdit::DisplayTimingMenu() { g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); posLabel = ScreenEdit::label; - posWarp = ScreenEdit::warp; } g_TimingDataInformation.rows[posLabel].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); - g_TimingDataInformation.rows[posWarp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } From 323f1b0059709741d1941639b42cdd2236e44cb5 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 16:04:17 -0400 Subject: [PATCH 139/333] [splittiming] Remove hack, just use bEnabled. Wish I saw this sooner. --- src/ScreenEdit.cpp | 62 ++++++++++++++-------------------------------- src/ScreenEdit.h | 2 +- 2 files changed, 20 insertions(+), 44 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0ff4b95235..2c547ac03d 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -562,23 +562,19 @@ static MenuDef g_SongInformation( MenuRowDef( ScreenEdit::max_bpm, "Max BPM", true, EditMode_Full, true, true, 0, NULL ) ); -static const MenuRowDef g_TimingDataLines[] = -{ - MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::stop, "Edit stop", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ), -}; static MenuDef g_TimingDataInformation( - "ScreenMiniMenuTimingDataInformation" - // fill this in dynamically too. + "ScreenMiniMenuTimingDataInformation", + MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::stop, "Edit stop", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -3159,43 +3155,23 @@ inline float ScreenEdit::GetBeat() void ScreenEdit::DisplayTimingMenu() { - g_TimingDataInformation.rows.clear(); - - for( unsigned i=0; im_bIsEditorStepTiming ) - { - continue; - } - - g_TimingDataInformation.rows.push_back(hl); - } - float fBeat = GetBeat(); TimingData &pTime = GetAppropriateTiming(); - - // TODO: Better way of guaranteeing that we don't go out of bounds between timings. - int posLabel = ScreenEdit::tickcount; - g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); + g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); - if( GAMESTATE->m_bIsEditorStepTiming ) - { - g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); - posLabel = ScreenEdit::label; - } - g_TimingDataInformation.rows[posLabel].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); - + g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index f783cf5368..68a2353a83 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -492,9 +492,9 @@ public: // time_signature, time_signature_numerator, time_signature_denominator, + label, tickcount, combo, - label, warp, NUM_TIMING_DATA_INFORMATION_CHOICES }; From e078e6beef6a3d45a2f799daa6e33d609ea21290 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 16:29:35 -0400 Subject: [PATCH 140/333] [splittiming] More SST setup. Song Timing shouldn't edit notes, only timing. --- src/ScreenEdit.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 2c547ac03d..cc2a677b3c 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1544,18 +1544,20 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // update enabled/disabled in g_AreaMenu bool bAreaSelected = m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1; - g_AreaMenu.rows[cut].bEnabled = bAreaSelected; + g_AreaMenu.rows[cut].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[copy].bEnabled = bAreaSelected; - g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty(); - g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1; - g_AreaMenu.rows[clear].bEnabled = bAreaSelected; - g_AreaMenu.rows[quantize].bEnabled = bAreaSelected; - g_AreaMenu.rows[turn].bEnabled = bAreaSelected; - g_AreaMenu.rows[transform].bEnabled = bAreaSelected; + g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty() && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1 && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[clear].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[quantize].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[turn].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[transform].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[alter].bEnabled = bAreaSelected; g_AreaMenu.rows[tempo].bEnabled = bAreaSelected; g_AreaMenu.rows[play].bEnabled = bAreaSelected; - g_AreaMenu.rows[record].bEnabled = bAreaSelected; + g_AreaMenu.rows[record].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[insert_and_shift].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[delete_and_shift].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[convert_to_pause].bEnabled = bAreaSelected; g_AreaMenu.rows[undo].bEnabled = m_bHasUndo; EditMiniMenu( &g_AreaMenu, SM_BackFromAreaMenu ); @@ -2065,6 +2067,11 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) HandleMainMenuChoice( play_selection ); break; case EDIT_BUTTON_RECORD_SELECTION: + if( !GAMESTATE->m_bIsEditorStepTiming ) + { + // broadcast message maybe. + break; + } if( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ) { HandleAreaMenuChoice( record ); @@ -2221,7 +2228,12 @@ void ScreenEdit::InputRecordPaused( const InputEventPlus &input, EditButton Edit break; case EDIT_BUTTON_RECORD_SELECTION: - TransitionEditState( STATE_RECORDING ); + if( GAMESTATE->m_bIsEditorStepTiming ) + TransitionEditState( STATE_RECORDING ); + else + { + // broadcast error maybe. + } break; case EDIT_BUTTON_RECORD_FROM_CURSOR: From 7c9b54e9f0d0c6cb611722a78a3c0439a4bf37db Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 13 May 2011 23:32:14 -0400 Subject: [PATCH 141/333] [splittiming] Fix ArrowEffects 1c4b21b. Almost had this one right...just needed more vars. --- src/ArrowEffects.cpp | 6 ++++-- src/GameState.h | 5 +++++ src/ScreenEdit.cpp | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index a0566826d1..e6f3831849 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -85,7 +85,8 @@ void ArrowEffects::Update() FOREACH_PlayerNumber( pn ) { const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; - const SongPosition &position = GAMESTATE->m_bIsEditorStepTiming ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; + const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsEditorStepTiming) + ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; PerPlayerData &data = g_EffectData[pn]; @@ -219,7 +220,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float bIsPastPeakOut = true; float fYOffset = 0; - const SongPosition &position = GAMESTATE->m_bIsEditorStepTiming ? pPlayerState->m_Position : GAMESTATE->m_Position; + const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsEditorStepTiming) + ? pPlayerState->m_Position : GAMESTATE->m_Position; /* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or * entirely time spacing (respectively). Occasionally, we tween between them. */ diff --git a/src/GameState.h b/src/GameState.h index 592b613dfe..0a6efc0e25 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -337,6 +337,11 @@ public: * * Different options are available depending on this setting. */ bool m_bIsEditorStepTiming; + /** + * @brief Are we presently in the Step Editor, where some rules apply differently? + * + * TODO: Find a better way to implement this. */ + bool m_bInStepEditor; BroadcastOnChange m_stEdit; BroadcastOnChange m_cdEdit; BroadcastOnChangePtr m_pEditSourceSteps; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index cc2a677b3c..2ff3b112dc 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -698,6 +698,7 @@ void ScreenEdit::Init() m_pSoundMusic = NULL; GAMESTATE->m_bIsEditorStepTiming = true; + GAMESTATE->m_bInStepEditor = true; SubscribeToMessage( "Judgment" ); @@ -858,6 +859,8 @@ ScreenEdit::~ScreenEdit() // Reset the GameState variable in case it's needed elsewhere. GAMESTATE->m_bIsEditorStepTiming = false; + // DEFINITELY reset the InStepEditor variable. + GAMESTATE->m_bInStepEditor = false; } void ScreenEdit::BeginScreen() From f4684b8cc3f3e0c924d581eb96c2958c3ab94716 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Fri, 13 May 2011 23:37:07 -0500 Subject: [PATCH 142/333] use player timing for autoplay row check --- src/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Player.cpp b/src/Player.cpp index f992b838d5..95878e4c1c 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -919,7 +919,7 @@ void Player::Update( float fDeltaTime ) /* We want to send the crossed row message exactly when we cross the row--not * .5 before the row. Use a very slow song (around 2 BPM) as a test case: without * rounding, autoplay steps early. -glenn */ - const int iRowNow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat ); + const int iRowNow = BeatToNoteRowNotRounded( m_pPlayerState->m_Position.m_fSongBeat ); if( iRowNow >= 0 ) { if( GAMESTATE->IsPlayerEnabled(m_pPlayerState) ) From e462049c1608c7accf82f5eb098ea3d98a52413a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 00:57:34 -0400 Subject: [PATCH 143/333] [splittiming] No more holds/rolls on Song Timing. --- src/ScreenEdit.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 2ff3b112dc..8ba386b31a 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2584,17 +2584,20 @@ void ScreenEdit::ScrollTo( float fDestinationBeat ) if( !EditIsBeingPressed(b) ) continue; - // create a new hold note - int iStartRow = BeatToNoteRow( min(fOriginalBeat, fDestinationBeat) ); - int iEndRow = BeatToNoteRow( max(fOriginalBeat, fDestinationBeat) ); + if( GAMESTATE->m_bIsEditorStepTiming ) + { + // create a new hold note + int iStartRow = BeatToNoteRow( min(fOriginalBeat, fDestinationBeat) ); + int iEndRow = BeatToNoteRow( max(fOriginalBeat, fDestinationBeat) ); - // Don't SaveUndo. We want to undo the whole hold, not just the last segment - // that the user made. Dragging the hold bigger can only absorb and remove - // other taps, so dragging won't cause us to exceed the note limit. - TapNote tn = EditIsBeingPressed(EDIT_BUTTON_LAY_ROLL) ? TAP_ORIGINAL_ROLL_HEAD : TAP_ORIGINAL_HOLD_HEAD; + // Don't SaveUndo. We want to undo the whole hold, not just the last segment + // that the user made. Dragging the hold bigger can only absorb and remove + // other taps, so dragging won't cause us to exceed the note limit. + TapNote tn = EditIsBeingPressed(EDIT_BUTTON_LAY_ROLL) ? TAP_ORIGINAL_ROLL_HEAD : TAP_ORIGINAL_HOLD_HEAD; - tn.pn = m_InputPlayerNumber; - m_NoteDataEdit.AddHoldNote( iCol, iStartRow, iEndRow, tn ); + tn.pn = m_InputPlayerNumber; + m_NoteDataEdit.AddHoldNote( iCol, iStartRow, iEndRow, tn ); + } } if( EditIsBeingPressed(EDIT_BUTTON_SCROLL_SELECT) ) From 361a6340db161f7518b86dced1af246edcc009f7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 01:03:39 -0400 Subject: [PATCH 144/333] [splittiming] No BG Changes in Step Timing. --- Themes/_fallback/Languages/en.ini | 1 + src/ScreenEdit.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 49bc09f431..0fbe2863dc 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1258,6 +1258,7 @@ This change creates notes past the end of the music and is not allowed.=This cha This will destroy all unsaved changes.=This will destroy all unsaved changes. Undo=Undo You must be in Step Timing Mode to edit the notes.=You must be in Step Timing Mode to edit the notes. +You must be in Song Timing Mode to edit BG Changes.=You must be in Song Timing Mode to edit BG Changes. Current beat=Current beat Current second=Current second diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8ba386b31a..1941179491 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1279,6 +1279,8 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime ) } static LocalizedString TAP_NOTE_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to edit the notes." ); +static LocalizedString BG_CHANGE_STEP_TIMING ( "ScreenEdit", "You must be in Song Timing Mode to edit BG Changes." ); + static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" ); static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" ); static ThemeMetric INVERT_SCROLL_BUTTONS ( "ScreenEdit", "InvertScrollSpeedButtons" ); @@ -1925,6 +1927,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) EditMiniMenu( &g_BackgroundChange, SM_BackFromBGChange ); } } + else + { + SCREENMAN->SystemMessage( BG_CHANGE_STEP_TIMING ); + } break; case EDIT_BUTTON_OPEN_COURSE_MENU: From 393dadcb1621fe6099556d9010f4ddb1f2627903 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 01:31:28 -0400 Subject: [PATCH 145/333] [splittiming] More SST protection. Also added InvalidSound for emphasis. --- Themes/_fallback/Languages/en.ini | 3 +++ src/ScreenEdit.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 0fbe2863dc..85147d8920 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1259,6 +1259,9 @@ This will destroy all unsaved changes.=This will destroy all unsaved changes. Undo=Undo You must be in Step Timing Mode to edit the notes.=You must be in Step Timing Mode to edit the notes. You must be in Song Timing Mode to edit BG Changes.=You must be in Song Timing Mode to edit BG Changes. +You must be in Step Timing Mode to record steps.=You must be in Step Timing Mode to record steps. +You must be in Step Timing Mode to insert beats and shift down.=You must be in Step Timing Mode to insert beats and shift down. +You must be in Step Timing Mode to delete beats and shift up.=You must be in Step Timing Mode to delete beats and shift up. Current beat=Current beat Current second=Current second diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 1941179491..e8cbb396e5 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1280,6 +1280,9 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime ) static LocalizedString TAP_NOTE_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to edit the notes." ); static LocalizedString BG_CHANGE_STEP_TIMING ( "ScreenEdit", "You must be in Song Timing Mode to edit BG Changes." ); +static LocalizedString RECORD_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to record steps." ); +static LocalizedString INSERT_BEAT_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to insert beats and shift down." ); +static LocalizedString DELETE_BEAT_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to delete beats and shift up." ); static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" ); static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" ); @@ -1316,6 +1319,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // Only allow steps to be hit in Step Timing. SCREENMAN->SystemMessage( TAP_NOTE_SONG_TIMING ); + SCREENMAN->PlayInvalidSound(); break; } @@ -1930,6 +1934,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) else { SCREENMAN->SystemMessage( BG_CHANGE_STEP_TIMING ); + SCREENMAN->PlayInvalidSound(); } break; @@ -2078,7 +2083,8 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) case EDIT_BUTTON_RECORD_SELECTION: if( !GAMESTATE->m_bIsEditorStepTiming ) { - // broadcast message maybe. + SCREENMAN->SystemMessage( RECORD_SONG_TIMING ); + SCREENMAN->PlayInvalidSound(); break; } if( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ) @@ -2117,7 +2123,14 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_INSERT: - HandleAreaMenuChoice( insert_and_shift ); + if( GAMESTATE->m_bIsEditorStepTiming ) + { + HandleAreaMenuChoice( insert_and_shift ); + } + else + { + SCREENMAN->SystemMessage( INSERT_BEAT_SONG_TIMING ); + } SCREENMAN->PlayInvalidSound(); break; @@ -2127,7 +2140,14 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_DELETE: - HandleAreaMenuChoice( delete_and_shift ); + if( GAMESTATE->m_bIsEditorStepTiming ) + { + HandleAreaMenuChoice( delete_and_shift ); + } + else + { + SCREENMAN->SystemMessage( DELETE_BEAT_SONG_TIMING ); + } SCREENMAN->PlayInvalidSound(); break; From 9909125b501ae51b398b1e58bc40e17d6dd5785d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 01:37:12 -0400 Subject: [PATCH 146/333] [splittiming] Let Linux have fun with this. I forgot which folder SongPosition.* goes in. --- src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 2a60163c84..178a263f39 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -373,7 +373,8 @@ ScoreDisplayBattle.cpp ScoreDisplayBattle.h \ ScoreDisplayCalories.cpp ScoreDisplayCalories.h \ ScoreDisplayLifeTime.cpp ScoreDisplayLifeTime.h \ ScoreDisplayNormal.cpp ScoreDisplayNormal.h ScoreDisplayOni.cpp ScoreDisplayOni.h \ -ScoreDisplayPercentage.cpp ScoreDisplayPercentage.h ScoreDisplayRave.cpp ScoreDisplayRave.h +ScoreDisplayPercentage.cpp ScoreDisplayPercentage.h ScoreDisplayRave.cpp ScoreDisplayRave.h \ +SongPosition.cpp SongPosition.h PCRE = ../extern/pcre/get.c ../extern/pcre/internal.h ../extern/pcre/maketables.c ../extern/pcre/pcre.c ../extern/pcre/pcre.h ../extern/pcre/study.c EXTRA_DIST += ../extern/pcre/chartables.c From 230fd47cf082d507c2047ab8ae480d2135cae86e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 01:41:20 -0400 Subject: [PATCH 147/333] [splittiming] This also needed SST care. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index e8cbb396e5..b97d7a77bb 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1561,7 +1561,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) g_AreaMenu.rows[quantize].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[turn].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[transform].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[alter].bEnabled = bAreaSelected; + g_AreaMenu.rows[alter].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; g_AreaMenu.rows[tempo].bEnabled = bAreaSelected; g_AreaMenu.rows[play].bEnabled = bAreaSelected; g_AreaMenu.rows[record].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; From d538c548c55a5d72c20f2b587d8ef84bed0780ea Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sat, 14 May 2011 00:43:06 -0500 Subject: [PATCH 148/333] [splittiming] add an option to revert timing for steps to the song's timing to the editor --- src/ScreenEdit.cpp | 14 ++++++++++++++ src/ScreenEdit.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index b97d7a77bb..569d631549 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -83,6 +83,7 @@ AutoScreenMessage( SM_BackFromTickcountChange ); AutoScreenMessage( SM_BackFromComboChange ); AutoScreenMessage( SM_BackFromLabelChange ); AutoScreenMessage( SM_BackFromWarpChange ); +AutoScreenMessage( SM_DoEraseStepTiming ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); AutoScreenMessage( SM_SaveSuccessful ); @@ -575,6 +576,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -2943,6 +2945,15 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) SetDirty( false ); } } + else if( SM == SM_DoEraseSplitTiming ) + { + if( ScreenPrompt::s_LastAnswer == ANSWER_YES ) + { + SaveUndo(); + m_pSteps->m_Timing = m_pSong->m_SongTiming; + SetDirty( true ); + } + } else if( SM == SM_DoSaveAndExit ) // just asked "save before exiting? yes, no, cancel" { switch( ScreenPrompt::s_LastAnswer ) @@ -3893,6 +3904,7 @@ static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tick static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." ); static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." ); +static LocalizedString CONFIRM_TIMING_ERASE ( "ScreenEdit", "Are you sure you want to erase this chart's timing data?" ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { switch( c ) @@ -3974,6 +3986,8 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ssprintf( "%.4f", GetAppropriateTiming().GetWarpAtBeat( GetBeat() ) ), 10 ); + case erase_step_timing: + ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); break; } } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 68a2353a83..68eabff5f5 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -496,6 +496,7 @@ public: tickcount, combo, warp, + erase_step_timing, NUM_TIMING_DATA_INFORMATION_CHOICES }; From cc27332f9c1848d247c3686e72206b81eeaa9567 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sat, 14 May 2011 00:57:20 -0500 Subject: [PATCH 149/333] [splittiming] add some missing strings to en.ini --- Themes/_fallback/Languages/en.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 85147d8920..beb4ac939d 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -854,6 +854,7 @@ Edit label=Edit label Edit warp=Edit warp Editor options=Options EditorShowBGChangesPlay=Show Backgrounds +Erase step timing=Erase step timing Effect=Effect EnableAttackSounds=Attack Sounds EnableMineHitSound=Mine Sounds @@ -1226,6 +1227,7 @@ Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. Enter a new Label value.=Enter a name for this section of the chart. Enter a new Warp value.=Enter the beat you will warp to when you reach this point. +Are you sure you want to erase this chart's timing data?=Are you sure you want to erase this chart's timing data? Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. Enter a new genre.=Enter a new genre. From a70f087b0ca5ab5bebf6a23c2a7031468662b93c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 02:14:00 -0400 Subject: [PATCH 150/333] [splittiming] Mino typoes. --- src/ScreenEdit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 569d631549..4fdec6b864 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -575,7 +575,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) ); @@ -2945,7 +2945,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) SetDirty( false ); } } - else if( SM == SM_DoEraseSplitTiming ) + else if( SM == SM_DoEraseStepTiming ) { if( ScreenPrompt::s_LastAnswer == ANSWER_YES ) { From fb0fb41ac233c75988fb1fda7f2d0b1ee14c7cc0 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 14 May 2011 21:35:43 +0700 Subject: [PATCH 151/333] initialize m_bIsEditorStepTiming with true, to be sure. --- src/GameState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 4a521e1ebb..88a090e8c5 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -128,7 +128,7 @@ GameState::GameState() : m_stEditSource( Message_EditSourceStepsTypeChanged ), m_iEditCourseEntryIndex( Message_EditCourseEntryIndexChanged ), m_sEditLocalProfileID( Message_EditLocalProfileIDChanged ), - m_bIsEditorStepTiming( false ) + m_bIsEditorStepTiming( true ) { g_pImpl = new GameStateImpl; From 682d679349aafbecca5debb025d18f8eee346b33 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 12:44:59 -0400 Subject: [PATCH 152/333] [splittiming] Versus scoring fix...wait. This is in the wrong branch. Transplant time! --- Themes/_fallback/Scripts/04 Scoring.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Themes/_fallback/Scripts/04 Scoring.lua b/Themes/_fallback/Scripts/04 Scoring.lua index 1c8c8df8b5..120177cd4d 100644 --- a/Themes/_fallback/Scripts/04 Scoring.lua +++ b/Themes/_fallback/Scripts/04 Scoring.lua @@ -89,11 +89,14 @@ r['DDR Extreme'] = function(params, pss) local totalItems = GetTotalItems(radarValues); local singleStep = (1 + totalItems) * totalItems / 2; if (not Shared.CurrentStep) then - Shared.CurrentStep = 0 + Shared.CurrentStep = {}; + Shared.CurrentStep["P1"] = 0; + Shared.CurrentStep["P2"] = 0; end; - Shared.CurrentStep = Shared.CurrentStep + 1; + local pn = PlayerNumberToString(params.Player); + Shared.CurrentStep[pn] = Shared.CurrentStep[pn] + 1; local stepValue = math.floor(baseScore /singleStep); - local stepLast = stepValue * Shared.CurrentStep; + local stepLast = stepValue * Shared.CurrentStep[pn]; pss:SetCurMaxScore(pss:GetCurMaxScore() + (stepLast * judgmentBase['TapNoteScore_W1'])); local judgeScore = 0; @@ -107,9 +110,9 @@ r['DDR Extreme'] = function(params, pss) end; local stepScore = judgeScore * stepLast; pss:SetScore(pss:GetScore() + stepScore); - if (Shared.CurrentStep >= totalItems) then -- Just in case. + if (Shared.CurrentStep[pn] >= totalItems) then -- Just in case. -- TODO: Implement the bonus for the last step? - Shared.CurrentStep = 0; -- Reset for the next song. + Shared.CurrentStep[pn] = 0; -- Reset for the next song. end; end; ----------------------------------------------------------- From f845dbc23200e3fdff6dbb3294aa2b6eb1f4fe0a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 12:44:59 -0400 Subject: [PATCH 153/333] Bring in the scoring fix from [splittiming]. --- Themes/_fallback/Scripts/04 Scoring.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Themes/_fallback/Scripts/04 Scoring.lua b/Themes/_fallback/Scripts/04 Scoring.lua index 1c8c8df8b5..120177cd4d 100644 --- a/Themes/_fallback/Scripts/04 Scoring.lua +++ b/Themes/_fallback/Scripts/04 Scoring.lua @@ -89,11 +89,14 @@ r['DDR Extreme'] = function(params, pss) local totalItems = GetTotalItems(radarValues); local singleStep = (1 + totalItems) * totalItems / 2; if (not Shared.CurrentStep) then - Shared.CurrentStep = 0 + Shared.CurrentStep = {}; + Shared.CurrentStep["P1"] = 0; + Shared.CurrentStep["P2"] = 0; end; - Shared.CurrentStep = Shared.CurrentStep + 1; + local pn = PlayerNumberToString(params.Player); + Shared.CurrentStep[pn] = Shared.CurrentStep[pn] + 1; local stepValue = math.floor(baseScore /singleStep); - local stepLast = stepValue * Shared.CurrentStep; + local stepLast = stepValue * Shared.CurrentStep[pn]; pss:SetCurMaxScore(pss:GetCurMaxScore() + (stepLast * judgmentBase['TapNoteScore_W1'])); local judgeScore = 0; @@ -107,9 +110,9 @@ r['DDR Extreme'] = function(params, pss) end; local stepScore = judgeScore * stepLast; pss:SetScore(pss:GetScore() + stepScore); - if (Shared.CurrentStep >= totalItems) then -- Just in case. + if (Shared.CurrentStep[pn] >= totalItems) then -- Just in case. -- TODO: Implement the bonus for the last step? - Shared.CurrentStep = 0; -- Reset for the next song. + Shared.CurrentStep[pn] = 0; -- Reset for the next song. end; end; ----------------------------------------------------------- From a5be839174d9be95f595492fdae8a267314f3cb8 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 13:33:12 -0400 Subject: [PATCH 154/333] [splittiming] Missed a break. --- src/ScreenEdit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 4fdec6b864..e6d2b477e8 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3986,6 +3986,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ssprintf( "%.4f", GetAppropriateTiming().GetWarpAtBeat( GetBeat() ) ), 10 ); + break; case erase_step_timing: ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); break; From 018b5152739ecc98ab5ef7dd4d146eba7f23d41a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 16:56:50 -0400 Subject: [PATCH 155/333] [splittiming] Abstract, minor cleanup on SMA. Time we get this format properly supported. --- src/NotesLoaderSM.cpp | 47 +++++++++++++++++-------------- src/NotesLoaderSM.h | 2 ++ src/NotesLoaderSMA.cpp | 63 +++++++++++++++--------------------------- src/NotesLoaderSSC.cpp | 22 +-------------- 4 files changed, 51 insertions(+), 83 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 280063f1b6..a71fa80a1a 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -103,6 +103,31 @@ bool SMLoader::LoadTimingFromFile( const RString &fn, TimingData &out ) return true; } +void SMLoader::ProcessBGChanges( Song &out, const RString &sValueName, const RString &sPath, const RString &sParam ) +{ + BackgroundLayer iLayer = BACKGROUND_LAYER_1; + if( sscanf(sValueName, "BGCHANGES%d", &*ConvertValue(&iLayer)) == 1 ) + enum_add(iLayer, -1); // #BGCHANGES2 = BACKGROUND_LAYER_2 + + bool bValid = iLayer>=0 && iLayerUserLog( "Song file", sPath, "has a #BGCHANGES tag \"%s\" that is out of range.", sValueName.c_str() ); + } + else + { + vector aBGChangeExpressions; + split( sParam, ",", aBGChangeExpressions ); + + for( unsigned b=0; b arrayBPMChangeExpressions; @@ -632,27 +657,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else if( sValueName.Left(strlen("BGCHANGES"))=="BGCHANGES" || sValueName=="ANIMATIONS" ) { - BackgroundLayer iLayer = BACKGROUND_LAYER_1; - if( sscanf(sValueName, "BGCHANGES%d", &*ConvertValue(&iLayer)) == 1 ) - enum_add(iLayer, -1); // #BGCHANGES2 = BACKGROUND_LAYER_2 - - bool bValid = iLayer>=0 && iLayerUserLog( "Song file", sPath, "has a #BGCHANGES tag \"%s\" that is out of range.", sValueName.c_str() ); - } - else - { - vector aBGChangeExpressions; - split( sParams[1], ",", aBGChangeExpressions ); - - for( unsigned b=0; b aFileNames; + GetApplicableFiles( sPath, aFileNames ); + + if( aFileNames.size() > 1 ) + { + LOG->UserLog( "Song", sPath, "has more than one SMA file. Only one SMA file is allowed per song." ); + return false; + } + ASSERT( aFileNames.size() == 1 ); + return LoadFromSMAFile( sPath + aFileNames[0], out ); +} + void SMALoader::LoadFromSMATokens( RString sStepsType, RString sDescription, @@ -83,20 +104,6 @@ void SMALoader::LoadFromSMATokens( out.TidyUpData(); } -bool SMALoader::LoadFromDir( const RString &sPath, Song &out ) -{ - vector aFileNames; - GetApplicableFiles( sPath, aFileNames ); - - if( aFileNames.size() > 1 ) - { - LOG->UserLog( "Song", sPath, "has more than one SMA file. There can be only one!" ); - return false; - } - ASSERT( aFileNames.size() == 1 ); - return LoadFromSMAFile( sPath + aFileNames[0], out ); -} - void SMALoader::TidyUpData( Song &song, bool bFromCache ) { SMLoader::TidyUpData( song, bFromCache ); @@ -265,27 +272,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else if( sValueName.Left(strlen("BGCHANGES"))=="BGCHANGES" || sValueName=="ANIMATIONS" ) { - BackgroundLayer iLayer = BACKGROUND_LAYER_1; - if( sscanf(sValueName, "BGCHANGES%d", &*ConvertValue(&iLayer)) == 1 ) - enum_add(iLayer, -1); // #BGCHANGES2 = BACKGROUND_LAYER_2 - - bool bValid = iLayer>=0 && iLayerUserLog( "Song file", sPath, "has a #BGCHANGES tag \"%s\" that is out of range.", sValueName.c_str() ); - } - else - { - vector aBGChangeExpressions; - split( sParams[1], ",", aBGChangeExpressions ); - - for( unsigned b=0; b(&iLayer)) == 1 ) - enum_add(iLayer, -1); // #BGCHANGES2 = BACKGROUND_LAYER_2 - - bool bValid = iLayer>=0 && iLayerUserLog( "Song file", sPath, "has a #BGCHANGES tag \"%s\" that is out of range.", sValueName.c_str() ); - } - else - { - vector aBGChangeExpressions; - split( sParams[1], ",", aBGChangeExpressions ); - - for( unsigned b=0; b Date: Sat, 14 May 2011 17:24:18 -0400 Subject: [PATCH 156/333] [splittiming] Abstract unused(?) #ATTACKS. --- src/NotesLoaderSM.cpp | 87 ++++++++++++++++++++++-------------------- src/NotesLoaderSM.h | 3 +- src/NotesLoaderSMA.cpp | 42 +------------------- src/NotesLoaderSSC.cpp | 42 +------------------- 4 files changed, 50 insertions(+), 124 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index a71fa80a1a..9e980aac14 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -128,6 +128,51 @@ void SMLoader::ProcessBGChanges( Song &out, const RString &sValueName, const RSt } } +void SMLoader::ProcessAttacks( Song &out, MsdFile::value_t sParams ) +{ + // Build the RString vector here so we can write it to file again later + for( unsigned s=1; s < sParams.params.size(); ++s ) + out.m_sAttackString.push_back( sParams[s] ); + + Attack attack; + float end = -9999; + + for( unsigned j=1; j < sParams.params.size(); ++j ) + { + vector sBits; + split( sParams[j], "=", sBits, false ); + + // Need an identifer and a value for this to work + if( sBits.size() < 2 ) + continue; + + TrimLeft( sBits[0] ); + TrimRight( sBits[0] ); + + if( !sBits[0].CompareNoCase("TIME") ) + attack.fStartSecond = strtof( sBits[1], NULL ); + else if( !sBits[0].CompareNoCase("LEN") ) + attack.fSecsRemaining = strtof( sBits[1], NULL ); + else if( !sBits[0].CompareNoCase("END") ) + end = strtof( sBits[1], NULL ); + else if( !sBits[0].CompareNoCase("MODS") ) + { + attack.sModifiers = sBits[1]; + + if( end != -9999 ) + { + attack.fSecsRemaining = end - attack.fStartSecond; + end = -9999; + } + + if( attack.fSecsRemaining < 0.0f ) + attack.fSecsRemaining = 0.0f; + + out.m_Attacks.push_back( attack ); + } + } +} + bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) { vector arrayBPMChangeExpressions; @@ -681,47 +726,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache // Attacks loaded from file else if( sValueName=="ATTACKS" ) { - // Build the RString vector here so we can write it to file again later - for( unsigned s=1; s < sParams.params.size(); ++s ) - out.m_sAttackString.push_back( sParams[s] ); - - Attack attack; - float end = -9999; - - for( unsigned j=1; j < sParams.params.size(); ++j ) - { - vector sBits; - split( sParams[j], "=", sBits, false ); - - // Need an identifer and a value for this to work - if( sBits.size() < 2 ) - continue; - - TrimLeft( sBits[0] ); - TrimRight( sBits[0] ); - - if( !sBits[0].CompareNoCase("TIME") ) - attack.fStartSecond = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("LEN") ) - attack.fSecsRemaining = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("END") ) - end = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("MODS") ) - { - attack.sModifiers = sBits[1]; - - if( end != -9999 ) - { - attack.fSecsRemaining = end - attack.fStartSecond; - end = -9999; - } - - if( attack.fSecsRemaining < 0.0f ) - attack.fSecsRemaining = 0.0f; - - out.m_Attacks.push_back( attack ); - } - } + ProcessAttacks( out, sParams ); } else if( sValueName=="NOTES" || sValueName=="NOTES2" ) diff --git a/src/NotesLoaderSM.h b/src/NotesLoaderSM.h index 636df83f43..b6bc97cd60 100644 --- a/src/NotesLoaderSM.h +++ b/src/NotesLoaderSM.h @@ -3,8 +3,8 @@ #include "GameConstantsAndTypes.h" #include "BackgroundUtil.h" +#include "MsdFile.h" // we require the struct from here. -class MsdFile; class Song; class Steps; class TimingData; @@ -34,6 +34,7 @@ namespace SMLoader void ProcessTickcounts( TimingData &, const RString ); void ProcessBGChanges( Song &out, const RString &sValueName, const RString &sPath, const RString &sParam ); + void ProcessAttacks( Song &out, MsdFile::value_t sParams ); } #endif diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index f8bd8ba970..6fe8620bf3 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -296,47 +296,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) // Attacks loaded from file else if( sValueName=="ATTACKS" ) { - // Build the RString vector here so we can write it to file again later - for( unsigned s=1; s < sParams.params.size(); ++s ) - out.m_sAttackString.push_back( sParams[s] ); - - Attack attack; - float end = -9999; - - for( unsigned j=1; j < sParams.params.size(); ++j ) - { - vector sBits; - split( sParams[j], "=", sBits, false ); - - // Need an identifer and a value for this to work - if( sBits.size() < 2 ) - continue; - - TrimLeft( sBits[0] ); - TrimRight( sBits[0] ); - - if( !sBits[0].CompareNoCase("TIME") ) - attack.fStartSecond = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("LEN") ) - attack.fSecsRemaining = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("END") ) - end = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("MODS") ) - { - attack.sModifiers = sBits[1]; - - if( end != -9999 ) - { - attack.fSecsRemaining = end - attack.fStartSecond; - end = -9999; - } - - if( attack.fSecsRemaining < 0.0f ) - attack.fSecsRemaining = 0.0f; - - out.m_Attacks.push_back( attack ); - } - } + SMLoader::ProcessAttacks( out, sParams ); } else if( sValueName=="NOTES" || sValueName=="NOTES2" ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 1dd82798a3..d50942c74d 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -335,47 +335,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach // Attacks loaded from file else if( sValueName=="ATTACKS" ) { - // Build the RString vector here so we can write it to file again later - for( unsigned s=1; s < sParams.params.size(); ++s ) - out.m_sAttackString.push_back( sParams[s] ); - - Attack attack; - float end = -9999; - - for( unsigned j=1; j < sParams.params.size(); ++j ) - { - vector sBits; - split( sParams[j], "=", sBits, false ); - - // Need an identifer and a value for this to work - if( sBits.size() < 2 ) - continue; - - TrimLeft( sBits[0] ); - TrimRight( sBits[0] ); - - if( !sBits[0].CompareNoCase("TIME") ) - attack.fStartSecond = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("LEN") ) - attack.fSecsRemaining = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("END") ) - end = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("MODS") ) - { - attack.sModifiers = sBits[1]; - - if( end != -9999 ) - { - attack.fSecsRemaining = end - attack.fStartSecond; - end = -9999; - } - - if( attack.fSecsRemaining < 0.0f ) - attack.fSecsRemaining = 0.0f; - - out.m_Attacks.push_back( attack ); - } - } + SMLoader::ProcessAttacks( out, sParams ); } else if( sValueName=="OFFSET" ) From 9196c695774a51382e9cda4ad41e4fa91ac6af9b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 17:34:22 -0400 Subject: [PATCH 157/333] [splittiming] Temp breakage for parsing. Going to do this the SSC way, because that's how we roll. --- src/NotesLoaderSMA.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 0fceb3977d..94d6ae9dbb 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -9,6 +9,16 @@ class Song; class Steps; class TimingData; +/** + * @brief The various states while parsing a .sma file. + */ +enum SMALoadingStates +{ + SMA_GETTING_SONG_INFO, /**< Retrieving song information. */ + SMA_GETTING_STEP_INFO, /**< Retrieving step information. */ + NUM_SMALoadingStates /**< The number of states used. */ +}; + /** @brief Reads a Song from a .SMA file. */ namespace SMALoader { @@ -25,8 +35,7 @@ namespace SMALoader bool LoadFromSMAFile( const RString &sPath, Song &out ); void GetApplicableFiles( const RString &sPath, vector &out ); - bool LoadTimingFromFile( const RString &fn, TimingData &out ); - void LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ); + bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong ); bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot ); bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong ); From 4b89c0fae76025e833f738a257ab2bd680a29fad Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 17:41:08 -0400 Subject: [PATCH 158/333] [splittiming] Abstraction, prep work. --- src/NotesLoaderSM.cpp | 31 ++++++++++++++++++------------- src/NotesLoaderSM.h | 1 + src/NotesLoaderSMA.cpp | 22 +++++++--------------- src/NotesLoaderSSC.cpp | 14 +------------- 4 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 9e980aac14..80d56ee33f 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -173,6 +173,23 @@ void SMLoader::ProcessAttacks( Song &out, MsdFile::value_t sParams ) } } +void SMLoader::ProcessInstrumentTracks( Song &out, const RString &sParam ) +{ + vector vs1; + split( sParam, ",", vs1 ); + FOREACH_CONST( RString, vs1, s ) + { + vector vs2; + split( *s, "=", vs2 ); + if( vs2.size() >= 2 ) + { + InstrumentTrack it = StringToInstrumentTrack( vs2[0] ); + if( it != InstrumentTrack_Invalid ) + out.m_sInstrumentTrackFile[it] = vs2[1]; + } + } +} + bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) { vector arrayBPMChangeExpressions; @@ -597,19 +614,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else if( sValueName=="INSTRUMENTTRACK" ) { - vector vs1; - split( sParams[1], ",", vs1 ); - FOREACH_CONST( RString, vs1, s ) - { - vector vs2; - split( *s, "=", vs2 ); - if( vs2.size() >= 2 ) - { - InstrumentTrack it = StringToInstrumentTrack( vs2[0] ); - if( it != InstrumentTrack_Invalid ) - out.m_sInstrumentTrackFile[it] = vs2[1]; - } - } + ProcessInstrumentTracks( out, sParams[1] ); } else if( sValueName=="MUSICLENGTH" ) diff --git a/src/NotesLoaderSM.h b/src/NotesLoaderSM.h index b6bc97cd60..8628d7dde2 100644 --- a/src/NotesLoaderSM.h +++ b/src/NotesLoaderSM.h @@ -35,6 +35,7 @@ namespace SMLoader void ProcessBGChanges( Song &out, const RString &sValueName, const RString &sPath, const RString &sParam ); void ProcessAttacks( Song &out, MsdFile::value_t sParams ); + void ProcessInstrumentTracks( Song &out, const RString &sParam ); } #endif diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 6fe8620bf3..ec6a8deb6f 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -120,8 +120,12 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) return false; } - out.m_SongTiming.m_sFile = sPath; - LoadTimingFromSMAFile( msd, out.m_SongTiming ); + out.m_SongTiming.m_sFile = sPath; // songs still have their fallback timing. + + int state = SMA_GETTING_SONG_INFO; + Steps* pNewNotes = NULL; + TimingData stepsTiming; + int iRowsPerBeat = -1; // Start with an invalid value: needed for checking. for( unsigned i=0; i vs1; - split( sParams[1], ",", vs1 ); - FOREACH_CONST( RString, vs1, s ) - { - vector vs2; - split( *s, "=", vs2 ); - if( vs2.size() >= 2 ) - { - InstrumentTrack it = StringToInstrumentTrack( vs2[0] ); - if( it != InstrumentTrack_Invalid ) - out.m_sInstrumentTrackFile[it] = vs2[1]; - } - } + SMLoader::ProcessInstrumentTracks( out, sParams[1] ); } else if( sValueName=="MUSICLENGTH" ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index d50942c74d..abb5a72adf 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -232,19 +232,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="INSTRUMENTTRACK" ) { - vector vs1; - split( sParams[1], ",", vs1 ); - FOREACH_CONST( RString, vs1, s ) - { - vector vs2; - split( *s, "=", vs2 ); - if( vs2.size() >= 2 ) - { - InstrumentTrack it = StringToInstrumentTrack( vs2[0] ); - if( it != InstrumentTrack_Invalid ) - out.m_sInstrumentTrackFile[it] = vs2[1]; - } - } + SMLoader::ProcessInstrumentTracks( out, sParams[1] ); } else if( sValueName=="MUSICLENGTH" ) From 6b0a9392908ffed50f18d29a37ecea2e8d4cbfc8 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sat, 14 May 2011 17:03:49 -0500 Subject: [PATCH 159/333] [splittiming] new EffectModes (not available from Lua yet), clarified error message --- src/Actor.cpp | 16 ++++++++++++++++ src/Actor.h | 4 ++++ src/GameState.cpp | 2 ++ src/SongPosition.cpp | 2 +- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 72a3ee3856..42b5eae89b 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -68,6 +68,12 @@ void Actor::SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBe g_fCurrentBGMBeatNoOffset = fBeatNoOffset; } +void Actor::SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ) +{ + g_vfCurrentBGMBeatPlayer[pn] = fBeat; + g_vfCurrentBGMBeatPlayerNoOffset[pn] = fBeatNoOffset; +} + void Actor::SetBGMLight( int iLightNumber, float fCabinetLights ) { ASSERT( iLightNumber < NUM_CabinetLight ); @@ -675,6 +681,16 @@ void Actor::UpdateInternal( float fDeltaTime ) m_fEffectDelta = g_fCurrentBGMBeat - m_fSecsIntoEffect; m_fSecsIntoEffect = g_fCurrentBGMBeat; break; + + case CLOCK_BGM_BEAT_PLAYER1: + m_fEffectDelta = g_vfCurrentBGMBeat[PlayerNumber_P1] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeat[PlayerNumber_P1]; + break; + + case CLOCK_BGM_BEAT_PLAYER2: + m_fEffectDelta = g_vfCurrentBGMBeat[PlayerNumber_P2] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeat[PlayerNumber_P2]; + break; case CLOCK_BGM_TIME: m_fEffectDelta = g_fCurrentBGMTime - m_fSecsIntoEffect; diff --git a/src/Actor.h b/src/Actor.h index 45d080dabe..91634a7649 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -109,6 +109,7 @@ public: virtual void LoadFromNode( const XNode* pNode ); static void SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBeatNoOffset ); + static void SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ); static void SetBGMLight( int iLightNumber, float fCabinetLights ); /** @@ -131,6 +132,8 @@ public: CLOCK_BGM_BEAT, CLOCK_BGM_TIME_NO_OFFSET, CLOCK_BGM_BEAT_NO_OFFSET, + CLOCK_BGM_BEAT_PLAYER1, + CLOCK_BGM_BEAT_PLAYER2, CLOCK_LIGHT_1 = 1000, CLOCK_LIGHT_LAST = 1100, NUM_CLOCKS @@ -713,6 +716,7 @@ protected: // global state static float g_fCurrentBGMTime, g_fCurrentBGMBeat; static float g_fCurrentBGMTimeNoOffset, g_fCurrentBGMBeatNoOffset; + static vector g_vfCurrentBGMBeatPlayer, g_vfCurrentBGMBeatPlayerNoOffset; private: // commands diff --git a/src/GameState.cpp b/src/GameState.cpp index 88a090e8c5..3f26469494 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -949,7 +949,9 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti if( bUpdatePlayers ) FOREACH_EnabledPlayer( pn ) if( m_pCurSteps[pn] ) + { m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); + Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 79e925658f..bcfee26f80 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -20,7 +20,7 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); // "Crash reason : -243478.890625 -48695.773438" - ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); + ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds is less than -2000!", m_fSongBeat, fPositionSeconds) ); m_fMusicSeconds = fPositionSeconds; From 1349350eb261c607e40ae29218990cc05a7ec30f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:04:11 -0400 Subject: [PATCH 160/333] [splittiming] Minor update. --- src/NotesLoaderSM.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 80d56ee33f..598c0d40ff 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -381,10 +381,7 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam ) const float fBeat = StringToFloat( vs2[0] ); - TimeSignatureSegment seg; - seg.m_iStartRow = BeatToNoteRow(fBeat); - seg.m_iNumerator = atoi( vs2[1] ); - seg.m_iDenominator = atoi( vs2[2] ); + TimeSignatureSegment seg( BeatToNoteRow( fBeat ), StringToInt( vs2[1] ), StringToInt( vs2[2] )); if( fBeat < 0 ) { From 11c4c2fd03e32904a96234910954dbfa9ad08301 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:04:31 -0400 Subject: [PATCH 161/333] [splittiming] Another tag or two. --- src/NotesLoaderSMA.cpp | 107 ++++++++++++++++++++++++++++------------- src/NotesLoaderSMA.h | 2 + 2 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index ec6a8deb6f..8890f7cfe3 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -39,6 +39,42 @@ bool SMALoader::LoadFromDir( const RString &sPath, Song &out ) return LoadFromSMAFile( sPath + aFileNames[0], out ); } +void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) +{ + vector vs1; + split( sParam, ",", vs1 ); + + FOREACH_CONST( RString, vs1, s1 ) + { + vector vs2; + split( *s1, "=", vs2 ); + + if( vs2.size() < 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid beats per measure change with %i values.", (int)vs2.size() ); + continue; + } + + const float fBeat = StringToFloat( vs2[0] ); + + TimeSignatureSegment seg( BeatToNoteRow( fBeat ), StringToInt( vs2[1] ), StringToInt( vs2[2] )); + + if( fBeat < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat ); + continue; + } + + if( seg.m_iNumerator < 1 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator ); + continue; + } + + out.AddTimeSignatureSegment( seg ); + } +} + void SMALoader::LoadFromSMATokens( RString sStepsType, RString sDescription, @@ -201,7 +237,8 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) } else if( sValueName=="LASTBEAT" ) { - ; } + ; + } else if( sValueName=="SONGFILENAME" ) { ; @@ -241,6 +278,41 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) } } + else if( sValueName=="SMAVERSION" ) + { + ; // ignore it. + } + + else if( sValueName=="ROWSPERBEAT" ) + { + /* This value is used to help translate the timings + * the SMA format uses. Starting with the second + * appearance, it delimits NoteData. Right now, this + * value doesn't seem to be editable in SMA. When it + * becomes so, make adjustments to this code. */ + if( iRowsPerBeat < 0 ) + { + vector arrayBeatChangeExpressions; + split( sParams[1], ",", arrayBeatChangeExpressions ); + + vector arrayBeatChangeValues; + split( arrayBeatChangeExpressions[0], "=", arrayBeatChangeValues ); + iRowsPerBeat = StringToInt(arrayBeatChangeValues[1]); + } + else + { + state = SMA_GETTING_STEP_INFO; + // start again. + } + } + + else if( sValueName=="BEATSPERMEASURE" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessBeatsPerMeasure( timing, sParams[1] ); + } + else if( sValueName=="SELECTABLE" ) { if(sParams[1].EqualsNoCase("YES")) @@ -329,20 +401,6 @@ void SMALoader::GetApplicableFiles( const RString &sPath, vector &out ) GetDirListing( sPath + RString("*.sma"), out ); } -bool SMALoader::LoadTimingFromFile( const RString &fn, TimingData &out ) -{ - MsdFile msd; - if( !msd.ReadFile( fn, true ) ) // unescape - { - LOG->UserLog( "Song file", fn, "couldn't be loaded: %s", msd.GetError().c_str() ); - return false; - } - - out.m_sFile = fn; - LoadTimingFromSMAFile( msd, out ); - return true; -} - void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) { out.m_fBeat0OffsetInSeconds = 0; @@ -362,24 +420,7 @@ void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) RString sValueName = sParams[0]; sValueName.MakeUpper(); - if( sValueName=="ROWSPERBEAT") - { - if( encountered ) - { - break; - } - encountered = true; - rowsPerMeasure = StringToInt( sParams[1] ); - } - else if( sValueName=="BEATSPERMEASURE" ) - { - TimeSignatureSegment new_seg; - new_seg.m_iStartRow = 0; - new_seg.m_iNumerator = StringToInt( sParams[1] ); - new_seg.m_iDenominator = 4; - out.AddTimeSignatureSegment( new_seg ); - } - else if( sValueName=="OFFSET" ) + if( sValueName=="OFFSET" ) { out.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); } diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 94d6ae9dbb..4d59e79f0a 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -40,6 +40,8 @@ namespace SMALoader bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot ); bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong ); bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression ); + + void ProcessBeatsPerMeasure( TimingData &out, const RString sParam ); }; #endif From 3ac85df29fdc3eee2b378cc7ef0aaa7b36f6574f Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sat, 14 May 2011 17:12:27 -0500 Subject: [PATCH 162/333] [splittiming] some. times in our lives. we all have pains. we all have sorrow --- src/Actor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Actor.h b/src/Actor.h index 91634a7649..deb9ba3716 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -5,6 +5,7 @@ #include "RageUtil_AutoPtr.h" #include "LuaReference.h" #include "EnumHelper.h" +#include "PlayerNumber.h" #include class XNode; struct lua_State; From efb37b47d7c4dce5fe8231a098864f0bdb3b79be Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:17:48 -0400 Subject: [PATCH 163/333] [splittiming] Hey FSX, catch! --- src/GameState.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 3f26469494..8205d4143f 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -947,12 +947,16 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti m_Position.UpdateSongPosition( fPositionSeconds, timing, timestamp ); if( bUpdatePlayers ) + { FOREACH_EnabledPlayer( pn ) + { if( m_pCurSteps[pn] ) { m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); - + } + } + } Actor::SetBGMTime( GAMESTATE->m_Position.m_fMusicSecondsVisible, GAMESTATE->m_Position.m_fSongBeatVisible, fPositionSeconds, GAMESTATE->m_Position.m_fSongBeatNoOffset ); // LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze ); } From 2652a7c10b18bdbbc49221c8f207297b92d461a9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:22:36 -0400 Subject: [PATCH 164/333] [splittiming] #OFFSET done. Now for the rest. --- src/NotesLoaderSMA.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 8890f7cfe3..9e9d2ab7b6 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -262,6 +262,11 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) //else if( sValueName=="SAMPLEPATH" ) //out.m_sMusicSamplePath = sParams[1]; + else if( sValueName=="LISTSORT" ) + { + ; + } + else if( sValueName=="DISPLAYBPM" ) { // #DISPLAYBPM:[xxx][xxx:xxx]|[*]; @@ -302,7 +307,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else { state = SMA_GETTING_STEP_INFO; - // start again. + pNewNotes = out.CreateSteps(); } } @@ -352,6 +357,15 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) } } + else if( sValueName=="OFFSET" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + timing.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); + } + + + else if( sValueName=="KEYSOUNDS" ) { split( sParams[1], ",", out.m_vsKeysoundFile ); @@ -371,7 +385,6 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) continue; } - Steps* pNewNotes = out.CreateSteps(); LoadFromSMATokens( sParams[1], sParams[2], @@ -387,7 +400,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) * We used to check for timing data in this section. That has * since been moved to a dedicated function. */ - else if( sValueName=="OFFSET" || sValueName=="BPMS" || sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) + else if( sValueName=="BPMS" || sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) ; else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); @@ -420,11 +433,7 @@ void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) RString sValueName = sParams[0]; sValueName.MakeUpper(); - if( sValueName=="OFFSET" ) - { - out.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); - } - else if( sValueName=="STOPS" ) + if( sValueName=="STOPS" ) { vector arrayFreezeExpressions; split( sParams[1], ",", arrayFreezeExpressions ); From 0464a86faf722a29695d74634d762debd7409280 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:36:46 -0400 Subject: [PATCH 165/333] [splittiming] More progress. --- src/NotesLoaderSM.cpp | 9 +- src/NotesLoaderSM.h | 7 ++ src/NotesLoaderSMA.cpp | 196 +++++++++++++++++++---------------------- src/NotesLoaderSMA.h | 3 + 4 files changed, 103 insertions(+), 112 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 598c0d40ff..360ceaf111 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -15,11 +15,6 @@ /** @brief The maximum file size for edits. */ const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60KB -/** - * @brief The highest allowable speed before Warps come in. - * - * This was brought in from StepMania 4's recent betas. */ -const float FAST_BPM_WARP = 9999999.f; void SMLoader::LoadFromSMTokens( RString sStepsType, @@ -251,9 +246,7 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam ) highspeedBeat = -1; } { - BPMSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(fBeat); - new_seg.SetBPM( fNewBPM ); + BPMSegment new_seg( BeatToNoteRow( fBeat ), fNewBPM ); out.AddBPMSegment( new_seg ); } } diff --git a/src/NotesLoaderSM.h b/src/NotesLoaderSM.h index 8628d7dde2..d1c4feded0 100644 --- a/src/NotesLoaderSM.h +++ b/src/NotesLoaderSM.h @@ -8,6 +8,13 @@ class Song; class Steps; class TimingData; + +/** + * @brief The highest allowable speed before Warps come in. + * + * This was brought in from StepMania 4's recent betas. */ +const float FAST_BPM_WARP = 9999999.f; + /** @brief Reads a Song from an .SM file. */ namespace SMLoader { diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 9e9d2ab7b6..0fd989a7b5 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -39,6 +39,91 @@ bool SMALoader::LoadFromDir( const RString &sPath, Song &out ) return LoadFromSMAFile( sPath + aFileNames[0], out ); } +float SMALoader::RowToBeat( RString sLine, const int iRowsPerBeat ) +{ + if( sLine.Right(0).MakeUpper() == "R" ) + { + sLine = sLine.Left(sLine.size()-1); + return StringToFloat( sLine ) / iRowsPerBeat; + } + else + { + return StringToFloat( sLine ); + } +} + +bool SMALoader::ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayBPMChangeExpressions; + split( sParam, ",", arrayBPMChangeExpressions ); + + // prepare storage variables for negative BPMs -> Warps. + float negBeat = -1; + float negBPM = 1; + float highspeedBeat = -1; + bool bNotEmpty = false; + + for( unsigned b=0; b arrayBPMChangeValues; + split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); + // XXX: Hard to tell which file caused this. + if( arrayBPMChangeValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #BPMs value \"%s\" (must have exactly one '='), ignored.", + arrayBPMChangeExpressions[b].c_str() ); + continue; + } + + bNotEmpty = true; + + const float fBeat = RowToBeat( arrayBPMChangeValues[0], iRowsPerBeat ); + const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); + + if( fNewBPM < 0.0f ) + { + out.m_bHasNegativeBpms = true; + negBeat = fBeat; + negBPM = fNewBPM; + } + else if( fNewBPM > 0.0f ) + { + // add in a warp. + if( negBPM < 0 ) + { + float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); + WarpSegment new_seg(negBeat, endBeat); + out.AddWarpSegment( new_seg ); + + negBeat = -1; + negBPM = 1; + } + // too fast. make it a warp. + if( fNewBPM > FAST_BPM_WARP ) + { + highspeedBeat = fBeat; + } + else + { + // add in a warp. + if( highspeedBeat > 0 ) + { + WarpSegment new_seg(highspeedBeat, fBeat); + out.AddWarpSegment( new_seg ); + highspeedBeat = -1; + } + { + BPMSegment new_seg( BeatToNoteRow( fBeat ), fNewBPM ); + out.AddBPMSegment( new_seg ); + } + } + } + } + + return bNotEmpty; +} + + void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) { vector vs1; @@ -364,7 +449,12 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) timing.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); } - + else if( sValueName=="BPMS" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessBPMs( timing, iRowsPerBeat, sParams[1] ); + } else if( sValueName=="KEYSOUNDS" ) { @@ -400,7 +490,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) * We used to check for timing data in this section. That has * since been moved to a dedicated function. */ - else if( sValueName=="BPMS" || sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) + else if( sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) ; else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); @@ -488,108 +578,6 @@ void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) } } - else if( sValueName=="BPMS" ) - { - vector arrayBPMChangeExpressions; - split( sParams[1], ",", arrayBPMChangeExpressions ); - - for( unsigned b=0; b arrayBPMChangeValues; - split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); - // XXX: Hard to tell which file caused this. - if( arrayBPMChangeValues.size() != 2 ) - { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() ); - continue; - } - - float fBeat = 0; - RString beat = arrayBPMChangeValues[0]; - if( beat.Right(0).MakeUpper() == "R" ) - { - beat = beat.Left(beat.size()-1); - fBeat = StringToFloat( beat ) / rowsPerMeasure; - } - else - { - fBeat = StringToFloat(beat); - } - - //float fBeat = StringToFloat( arrayBPMChangeValues[0] ); - const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); - // XXX: Remove Negatives Bug? - BPMSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(fBeat); - new_seg.SetBPM( fNewBPM ); - - // convert negative BPMs into Warp segments - if( fNewBPM < 0.0f ) - { - vector arrayNextBPMChangeValues; - // get next bpm in sequence - if((b+1) < arrayBPMChangeExpressions.size()) - { - split( arrayBPMChangeExpressions[b+1], "=", arrayNextBPMChangeValues ); - const float fNextPositiveBeat = StringToFloat( arrayNextBPMChangeValues[0] ); - const float fNextPositiveBPM = StringToFloat( arrayNextBPMChangeValues[1] ); - - // tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition) - float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); - //float fWarpLengthBeats = fNextPositiveBeat + fDeltaBeat; - WarpSegment wsTemp(BeatToNoteRow(fBeat),fDeltaBeat); - arrayWarpsFromNegativeBPMs.push_back(wsTemp); - - /* - LOG->Trace( ssprintf("==NotesLoSM negbpm==\nfnextposbeat = %f, fnextposbpm = %f,\nfdelta = %f, fwarpto = %f", - fNextPositiveBeat, - fNextPositiveBPM, - fDeltaBeat, - fWarpToBeat - ) ); - */ - /* - LOG->Trace( ssprintf("==Negative/Subtractive BPM in NotesLoader==\nNegBPM has noterow = %i, BPM = %f\nNextBPM @ noterow %i\nDelta value = %i noterows\nThis warp will have us end up at noterow %i", - BeatToNoteRow(fBeat), fNewBPM, - BeatToNoteRow(fNextPositiveBeat), - BeatToNoteRow(fDeltaBeat), - BeatToNoteRow(fWarpToBeat)) - ); - */ - //float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); - /* - LOG->Trace( ssprintf("==NotesLoader Delta as NoteRows==\nfDeltaBeat = %f (beat)\nfDeltaBeat = (NextBPMSeg %f - abs(fBPS %f)) + (nextStartRow %i - thisRow %i)", - fDeltaBeat,(fNextPositiveBPM/60.0f),abs(fNewBPM/60.0f),BeatToNoteRow(fNextPositiveBeat),BeatToNoteRow(fBeat)) - ); - */ - - out.AddBPMSegment( new_seg ); - - continue; - } - else - { - // last BPM is a negative one? ugh. -aj (MAX_NOTE_ROW exists btw) - out.AddBPMSegment( new_seg ); - } - } - - if(fNewBPM > 0.0f) - out.AddBPMSegment( new_seg ); - else - { - out.m_bHasNegativeBpms = true; - // only add Negative BPMs in quirks mode -aj - if( PREFSMAN->m_bQuirksMode ) - out.AddBPMSegment( new_seg ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM ); - } - } - } - - // Note: Even though it is possible to have Negative BPMs and Stops in // a song along with Warps, we should not support files that contain // both styles of warp tricks (Negatives vs. #WARPS). diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 4d59e79f0a..5c7300d133 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -42,6 +42,9 @@ namespace SMALoader bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression ); void ProcessBeatsPerMeasure( TimingData &out, const RString sParam ); + bool ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam ); + + float RowToBeat( RString sLine, const int iRowsPerBeat ); }; #endif From 725224863dfe7c875b2d0e3cac8b1fead6e47ae4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:44:43 -0400 Subject: [PATCH 166/333] [splittiming] SMA stops and delays. --- src/NotesLoaderSMA.cpp | 208 ++++++++++++++++++++++------------------- src/NotesLoaderSMA.h | 2 + 2 files changed, 116 insertions(+), 94 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 0fd989a7b5..352def3295 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -123,6 +123,105 @@ bool SMALoader::ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RStr return bNotEmpty; } +void SMALoader::ProcessStops( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayFreezeExpressions; + split( sParam, ",", arrayFreezeExpressions ); + + // Prepare variables for negative stop conversion. + float negBeat = -1; + float negPause = 0; + + for( unsigned f=0; f arrayFreezeValues; + split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); + if( arrayFreezeValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #STOPS value \"%s\" (must have exactly one '='), ignored.", + arrayFreezeExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = RowToBeat( arrayFreezeValues[0], iRowsPerBeat ); + const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); + + // Process the prior stop. + if( negPause > 0 ) + { + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + if( negBeat + fSkipBeats > fFreezeBeat ) + fSkipBeats = fFreezeBeat - negBeat; + + WarpSegment ws( negBeat, negBeat + fSkipBeats); + out.AddWarpSegment( ws ); + + negBeat = -1; + negPause = 0; + } + + if( fFreezeSeconds < 0.0f ) + { + negBeat = fFreezeBeat; + negPause = -fFreezeSeconds; + } + else if( fFreezeSeconds > 0.0f ) + { + StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); + out.AddStopSegment( ss ); + } + + } + + // Process the prior stop if there was one. + if( negPause > 0 ) + { + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + WarpSegment ws( negBeat, negBeat + fSkipBeats); + out.AddWarpSegment( ws ); + } +} + +void SMALoader::ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayDelayExpressions; + split( sParam, ",", arrayDelayExpressions ); + + for( unsigned f=0; f arrayDelayValues; + split( arrayDelayExpressions[f], "=", arrayDelayValues ); + if( arrayDelayValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #DELAYS value \"%s\" (must have exactly one '='), ignored.", + arrayDelayExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = RowToBeat( arrayDelayValues[0], iRowsPerBeat ); + const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); + + StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); + // XXX: Remove Negatives Bug? + new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); + new_seg.m_fStopSeconds = fFreezeSeconds; + + // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + + if(fFreezeSeconds > 0.0f) + out.AddStopSegment( new_seg ); + else + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); + } +} void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) { @@ -456,6 +555,20 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) ProcessBPMs( timing, iRowsPerBeat, sParams[1] ); } + else if( sValueName=="STOPS" || sValueName=="FREEZES" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessStops( timing, iRowsPerBeat, sParams[1] ); + } + + else if( sValueName=="DELAYS" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessDelays( timing, iRowsPerBeat, sParams[1] ); + } + else if( sValueName=="KEYSOUNDS" ) { split( sParams[1], ",", out.m_vsKeysoundFile ); @@ -490,7 +603,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) * We used to check for timing data in this section. That has * since been moved to a dedicated function. */ - else if( sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) + else if( sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) ; else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); @@ -504,99 +617,6 @@ void SMALoader::GetApplicableFiles( const RString &sPath, vector &out ) GetDirListing( sPath + RString("*.sma"), out ); } -void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out ) -{ - out.m_fBeat0OffsetInSeconds = 0; - out.m_BPMSegments.clear(); - out.m_StopSegments.clear(); - out.m_WarpSegments.clear(); - out.m_vTimeSignatureSegments.clear(); - - vector arrayWarpsFromNegativeBPMs; - //vector arrayWarpsFromNegativeStops; - int rowsPerMeasure = 0; - bool encountered = false; - - for( unsigned i=0; i arrayFreezeExpressions; - split( sParams[1], ",", arrayFreezeExpressions ); - - for( unsigned f=0; f arrayFreezeValues; - split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); - if( arrayFreezeValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayFreezeExpressions[f].c_str() ); - continue; - } - - float fFreezeBeat = 0; - RString beat = arrayFreezeValues[0]; - if( beat.Right(0).MakeUpper() == "R" ) - { - beat = beat.Left(beat.size()-1); - fFreezeBeat = StringToFloat( beat ) / rowsPerMeasure; - } - else - { - fFreezeBeat = StringToFloat(beat); - } - - //float fFreezeBeat = StringToFloat( arrayBPMChangeValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); - // XXX: Remove Negatives Bug? - new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); - new_seg.m_fStopSeconds = fFreezeSeconds; - - if(fFreezeSeconds > 0.0f) - { - // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - else - { - // negative stops (hi JS!) -aj - if( PREFSMAN->m_bQuirksMode ) - { - // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } - } - } - - // Note: Even though it is possible to have Negative BPMs and Stops in - // a song along with Warps, we should not support files that contain - // both styles of warp tricks (Negatives vs. #WARPS). - // If Warps have been populated from Negative BPMs, then go through that - // instead of using the data in the Warps tag. This should be above, - // but it breaks compiling so... - if(arrayWarpsFromNegativeBPMs.size() > 0) - { - // zomg we already have some warps... - for( unsigned j=0; jTrace( "SMALoader::LoadEditFromFile(%s)", sEditFilePath.c_str() ); diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 5c7300d133..089eabe5ca 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -43,6 +43,8 @@ namespace SMALoader void ProcessBeatsPerMeasure( TimingData &out, const RString sParam ); bool ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessStops( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam ); float RowToBeat( RString sLine, const int iRowsPerBeat ); }; From 68272d4fdaecd1d90e532970196487fb97e23d62 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sat, 14 May 2011 17:56:39 -0500 Subject: [PATCH 167/333] [splittiming] blah --- src/Actor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 42b5eae89b..6d276ac473 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -683,13 +683,13 @@ void Actor::UpdateInternal( float fDeltaTime ) break; case CLOCK_BGM_BEAT_PLAYER1: - m_fEffectDelta = g_vfCurrentBGMBeat[PlayerNumber_P1] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeat[PlayerNumber_P1]; + m_fEffectDelta = g_vfCurrentBGMBeat[PLAYER_1] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeat[PLAYER_1]; break; case CLOCK_BGM_BEAT_PLAYER2: - m_fEffectDelta = g_vfCurrentBGMBeat[PlayerNumber_P2] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeat[PlayerNumber_P2]; + m_fEffectDelta = g_vfCurrentBGMBeat[PLAYER_2] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeat[PLAYER_2]; break; case CLOCK_BGM_TIME: From 600599569801b131c65957a516fd147bc977ecf9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 18:56:58 -0400 Subject: [PATCH 168/333] [splittiming] #MULTIPLIER tag. Acts like #COMBO. Well, it really does more, but they are more Pump specific behavior right now. Let's try to stick with things that can work for all on this parser. --- src/NotesLoaderSMA.cpp | 66 +++++++++++++++++++++++++++++++++++++++++- src/NotesLoaderSMA.h | 2 ++ src/NotesLoaderSSC.cpp | 2 +- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 352def3295..4a20ff4b14 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -223,6 +223,53 @@ void SMALoader::ProcessDelays( TimingData &out, const int iRowsPerBeat, const RS } } +void SMALoader::ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayTickcountExpressions; + split( sParam, ",", arrayTickcountExpressions ); + + for( unsigned f=0; f arrayTickcountValues; + split( arrayTickcountExpressions[f], "=", arrayTickcountValues ); + if( arrayTickcountValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #TICKCOUNTS value \"%s\" (must have exactly one '='), ignored.", + arrayTickcountExpressions[f].c_str() ); + continue; + } + + const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], iRowsPerBeat ); + int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT); + + TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks ); + out.AddTickcountSegment( new_seg ); + } +} + +void SMALoader::ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayMultiplierExpressions; + split( sParam, ",", arrayMultiplierExpressions ); + + for( unsigned f=0; f arrayMultiplierValues; + split( arrayMultiplierExpressions[f], "=", arrayMultiplierValues ); + if( arrayMultiplierValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #MULTIPLIER value \"%s\" (must have exactly one '='), ignored.", + arrayMultiplierExpressions[f].c_str() ); + continue; + } + const float fComboBeat = RowToBeat( arrayMultiplierValues[0], iRowsPerBeat ); + const int iCombos = StringToInt( arrayMultiplierValues[1] ); + ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); + out.AddComboSegment( new_seg ); + } +} + void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) { vector vs1; @@ -569,6 +616,23 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) ProcessDelays( timing, iRowsPerBeat, sParams[1] ); } + else if( sValueName=="TICKCOUNT" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessTickcounts( timing, iRowsPerBeat, sParams[1] ); + } + + else if( sValueName=="SPEED" ) + { + ; // This is something we should consider implementing. + } + + else if( sValueName=="MULTIPLIER" ) + { + ProcessMultipliers( pNewNotes->m_Timing, iRowsPerBeat, sParams[1] ); + } + else if( sValueName=="KEYSOUNDS" ) { split( sParams[1], ",", out.m_vsKeysoundFile ); @@ -603,7 +667,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) * We used to check for timing data in this section. That has * since been moved to a dedicated function. */ - else if( sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" ) + else if( sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" ) ; else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 089eabe5ca..1c40b462f2 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -45,6 +45,8 @@ namespace SMALoader bool ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessStops( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam ); float RowToBeat( RString sLine, const int iRowsPerBeat ); }; diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index abb5a72adf..74015106f5 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -120,7 +120,7 @@ void SSCLoader::ProcessCombos( TimingData &out, const RString sParam ) continue; } const float fComboBeat = StringToFloat( arrayComboValues[0] ); - const int iCombos = atoi( arrayComboValues[1] ); + const int iCombos = StringToInt( arrayComboValues[1] ); ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); out.AddComboSegment( new_seg ); } From 1cf2f266ebd53c49c909b8d387d8a83e6c329c06 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 19:05:01 -0400 Subject: [PATCH 169/333] [splittiming] Actor compiles, but not links here. Perhaps I'm doing it wrong? --- src/Actor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 6d276ac473..e41d573059 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -683,13 +683,13 @@ void Actor::UpdateInternal( float fDeltaTime ) break; case CLOCK_BGM_BEAT_PLAYER1: - m_fEffectDelta = g_vfCurrentBGMBeat[PLAYER_1] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeat[PLAYER_1]; + m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_1] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayer[PLAYER_1]; break; case CLOCK_BGM_BEAT_PLAYER2: - m_fEffectDelta = g_vfCurrentBGMBeat[PLAYER_2] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeat[PLAYER_2]; + m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_2] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayer[PLAYER_2]; break; case CLOCK_BGM_TIME: From 75f19591227c1dfc77c90d5d127f782864bfe21d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 19:09:23 -0400 Subject: [PATCH 170/333] [splittiming] Last seen tag. Time to try to make clean and give it a go. --- src/NotesLoaderSMA.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 4a20ff4b14..9cfca78a83 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -633,6 +633,11 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) ProcessMultipliers( pNewNotes->m_Timing, iRowsPerBeat, sParams[1] ); } + else if( sValueName=="METERTYPE" ) + { + ; // We don't use this...yet. + } + else if( sValueName=="KEYSOUNDS" ) { split( sParams[1], ",", out.m_vsKeysoundFile ); @@ -663,10 +668,6 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) out.AddSteps( pNewNotes ); } - /* - * We used to check for timing data in this section. That has - * since been moved to a dedicated function. - */ else if( sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" ) ; else From 5a06315926bfd907422304faa2b81f338dd22b04 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 19:34:57 -0400 Subject: [PATCH 171/333] [splittiming] Right, song timing always is X/4. --- src/NotesLoaderSMA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 9cfca78a83..f845127975 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -288,7 +288,7 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) const float fBeat = StringToFloat( vs2[0] ); - TimeSignatureSegment seg( BeatToNoteRow( fBeat ), StringToInt( vs2[1] ), StringToInt( vs2[2] )); + TimeSignatureSegment seg( BeatToNoteRow( fBeat ), StringToInt( vs2[1] ), 4 ); if( fBeat < 0 ) { From 574fee596e94a8facfcff1cc7e67c621d1caecd9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 20:04:33 -0400 Subject: [PATCH 172/333] [splittiming] Convert properly. --- src/NotesLoaderSMA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index f845127975..2d17557deb 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -41,7 +41,7 @@ bool SMALoader::LoadFromDir( const RString &sPath, Song &out ) float SMALoader::RowToBeat( RString sLine, const int iRowsPerBeat ) { - if( sLine.Right(0).MakeUpper() == "R" ) + if( sLine.find("R") || sLine.find("r") ) { sLine = sLine.Left(sLine.size()-1); return StringToFloat( sLine ) / iRowsPerBeat; From a32a03b2e98b933d604710a0ec57a7d4f7cb9eaa Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 20:05:27 -0400 Subject: [PATCH 173/333] [splittiming] Trying to restore #COMBOS. --- src/Actor.cpp | 16 ---------------- src/Actor.h | 5 ----- src/GameState.cpp | 2 +- src/ScoreKeeperNormal.cpp | 2 +- 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index e41d573059..72a3ee3856 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -68,12 +68,6 @@ void Actor::SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBe g_fCurrentBGMBeatNoOffset = fBeatNoOffset; } -void Actor::SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ) -{ - g_vfCurrentBGMBeatPlayer[pn] = fBeat; - g_vfCurrentBGMBeatPlayerNoOffset[pn] = fBeatNoOffset; -} - void Actor::SetBGMLight( int iLightNumber, float fCabinetLights ) { ASSERT( iLightNumber < NUM_CabinetLight ); @@ -681,16 +675,6 @@ void Actor::UpdateInternal( float fDeltaTime ) m_fEffectDelta = g_fCurrentBGMBeat - m_fSecsIntoEffect; m_fSecsIntoEffect = g_fCurrentBGMBeat; break; - - case CLOCK_BGM_BEAT_PLAYER1: - m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_1] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayer[PLAYER_1]; - break; - - case CLOCK_BGM_BEAT_PLAYER2: - m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_2] - m_fSecsIntoEffect; - m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayer[PLAYER_2]; - break; case CLOCK_BGM_TIME: m_fEffectDelta = g_fCurrentBGMTime - m_fSecsIntoEffect; diff --git a/src/Actor.h b/src/Actor.h index deb9ba3716..45d080dabe 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -5,7 +5,6 @@ #include "RageUtil_AutoPtr.h" #include "LuaReference.h" #include "EnumHelper.h" -#include "PlayerNumber.h" #include class XNode; struct lua_State; @@ -110,7 +109,6 @@ public: virtual void LoadFromNode( const XNode* pNode ); static void SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBeatNoOffset ); - static void SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ); static void SetBGMLight( int iLightNumber, float fCabinetLights ); /** @@ -133,8 +131,6 @@ public: CLOCK_BGM_BEAT, CLOCK_BGM_TIME_NO_OFFSET, CLOCK_BGM_BEAT_NO_OFFSET, - CLOCK_BGM_BEAT_PLAYER1, - CLOCK_BGM_BEAT_PLAYER2, CLOCK_LIGHT_1 = 1000, CLOCK_LIGHT_LAST = 1100, NUM_CLOCKS @@ -717,7 +713,6 @@ protected: // global state static float g_fCurrentBGMTime, g_fCurrentBGMBeat; static float g_fCurrentBGMTimeNoOffset, g_fCurrentBGMBeatNoOffset; - static vector g_vfCurrentBGMBeatPlayer, g_vfCurrentBGMBeatPlayerNoOffset; private: // commands diff --git a/src/GameState.cpp b/src/GameState.cpp index 8205d4143f..abb3c63552 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -953,7 +953,7 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti if( m_pCurSteps[pn] ) { m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); - Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); + // Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); } } } diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index 36c405501e..8aaa35ffcf 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -443,7 +443,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH if( iNumBreakCombo == 0 ) { - TimingData td = GAMESTATE->m_pCurSong->m_SongTiming; + TimingData td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing; int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier; } From 77dbafe9965a05c40e0d957a03a779b7397e21e1 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 20:13:46 -0400 Subject: [PATCH 174/333] [splittiming] Found the other location. Is there perhaps more to this? Hopefully not. --- src/ScoreKeeperNormal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index 8aaa35ffcf..d1530a9be0 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -463,7 +463,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn if ( tns >= m_MinScoreToContinueCombo ) { m_pPlayerStageStats->m_iCurMissCombo = 0; - TimingData td = GAMESTATE->m_pCurSong->m_SongTiming; + TimingData td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing; int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier; } From 0fc49d9da996d59cefe5557abd146ac7a34d2e7d Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 19:27:25 -0500 Subject: [PATCH 175/333] [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. --- Docs/Changelog_sm5.txt | 4 ++++ Themes/_fallback/metrics.ini | 2 ++ src/SongUtil.cpp | 34 +++++++++++++++++++++++----------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index cba431e5b8..0ad0e45592 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,10 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/14 +---------- +* [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] + 2011/05/11 ---------- * [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 668d96827b..cd36f351cc 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -857,7 +857,9 @@ ShowRoulette=true ShowRandom=false ShowPortal=false +ShowSectionsInBPMSort=true SortBPMDivision=20 +ShowSectionsInLengthSort=true SortLengthDivision=5 MostPlayedSongsToShow=30 diff --git a/src/SongUtil.cpp b/src/SongUtil.cpp index 2641f860f0..3d83420167 100644 --- a/src/SongUtil.cpp +++ b/src/SongUtil.cpp @@ -21,6 +21,8 @@ ThemeMetric SORT_BPM_DIVISION ( "MusicWheel", "SortBPMDivision" ); ThemeMetric SORT_LENGTH_DIVISION ( "MusicWheel", "SortLengthDivision" ); +ThemeMetric SHOW_SECTIONS_IN_BPM_SORT ( "MusicWheel", "ShowSectionsInBPMSort" ); +ThemeMetric SHOW_SECTIONS_IN_LENGTH_SORT ( "MusicWheel", "ShowSectionsInLengthSort" ); bool SongCriteria::Matches( const Song *pSong ) const { @@ -598,20 +600,30 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so return SORT_NOT_AVAILABLE.GetValue(); case SORT_BPM: { - const int iBPMGroupSize = SORT_BPM_DIVISION; - DisplayBpms bpms; - pSong->GetDisplayBpms( bpms ); - int iMaxBPM = (int)bpms.GetMax(); - iMaxBPM += iBPMGroupSize - (iMaxBPM%iBPMGroupSize) - 1; - return ssprintf("%03d-%03d",iMaxBPM-(iBPMGroupSize-1), iMaxBPM); + if( SHOW_SECTIONS_IN_BPM_SORT ) + { + const int iBPMGroupSize = SORT_BPM_DIVISION; + DisplayBpms bpms; + pSong->GetDisplayBpms( bpms ); + int iMaxBPM = (int)bpms.GetMax(); + iMaxBPM += iBPMGroupSize - (iMaxBPM%iBPMGroupSize) - 1; + return ssprintf("%03d-%03d",iMaxBPM-(iBPMGroupSize-1), iMaxBPM); + } + else + return RString(); } case SORT_LENGTH: { - const int iSortLengthSize = SORT_LENGTH_DIVISION; - int iMaxLength = (int)pSong->m_fMusicLengthSeconds; - iMaxLength += (iSortLengthSize - (iMaxLength%iSortLengthSize) - 1); - int iMinLength = iMaxLength - (iSortLengthSize-1); - return ssprintf( "%s-%s", SecondsToMMSS(iMinLength).c_str(), SecondsToMMSS(iMaxLength).c_str() ); + if( SHOW_SECTIONS_IN_LENGTH_SORT ) + { + const int iSortLengthSize = SORT_LENGTH_DIVISION; + int iMaxLength = (int)pSong->m_fMusicLengthSeconds; + iMaxLength += (iSortLengthSize - (iMaxLength%iSortLengthSize) - 1); + int iMinLength = iMaxLength - (iSortLengthSize-1); + return ssprintf( "%s-%s", SecondsToMMSS(iMinLength).c_str(), SecondsToMMSS(iMaxLength).c_str() ); + } + else + return RString(); } case SORT_POPULARITY: case SORT_RECENT: From aec111214444ecd720b048e9a7ccdd4a3ef10c64 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 19:36:50 -0500 Subject: [PATCH 176/333] [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. --- Docs/Changelog_sm5.txt | 1 + src/ScreenEvaluation.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 0ad0e45592..94335c16d0 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -11,6 +11,7 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/14 ---------- * [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] +* [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] 2011/05/11 ---------- diff --git a/src/ScreenEvaluation.cpp b/src/ScreenEvaluation.cpp index 76c40f03a1..de756c34fc 100644 --- a/src/ScreenEvaluation.cpp +++ b/src/ScreenEvaluation.cpp @@ -370,6 +370,11 @@ void ScreenEvaluation::Init() // init bonus area if( SHOW_BONUS_AREA ) { + // In course mode, we need to make sure the bar doesn't overflow. -aj + float fDivider = 1.0f; + if( GAMESTATE->IsCourseMode() ) + fDivider = fDivider / GAMESTATE->m_pCurCourse->m_vEntries.size(); + FOREACH_EnabledPlayer( p ) { m_sprBonusFrame[p].Load( THEME->GetPathG(m_sName,ssprintf("BonusFrame p%d",p+1)) ); @@ -382,7 +387,7 @@ void ScreenEvaluation::Init() for( int r=0; rGetPathG(m_sName,ssprintf("BarPossible p%d",p+1)) ); - m_sprPossibleBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * m_pStageStats->m_player[p].m_radarPossible[r] ); + m_sprPossibleBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * m_pStageStats->m_player[p].m_radarPossible[r] * fDivider ); m_sprPossibleBar[p][r].SetName( ssprintf("BarPossible%dP%d",r+1,p+1) ); ActorUtil::LoadAllCommands( m_sprPossibleBar[p][r], m_sName ); SET_XY( m_sprPossibleBar[p][r] ); @@ -390,7 +395,7 @@ void ScreenEvaluation::Init() m_sprActualBar[p][r].Load( THEME->GetPathG(m_sName,ssprintf("BarActual p%d",p+1)) ); // should be out of the possible bar, not actual (whatever value that is at) - m_sprActualBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * m_pStageStats->m_player[p].m_radarActual[r] ); + m_sprActualBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * m_pStageStats->m_player[p].m_radarActual[r] * fDivider ); float value = (float)100 * m_sprActualBar[p][r].GetUnzoomedWidth() / m_sprPossibleBar[p][r].GetUnzoomedWidth(); LOG->Trace("Radar bar %d of 5 - %f percent", r, value); From f4800b0e070c39e3618af3d85305da90f4e6d4e6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 14 May 2011 20:37:29 -0400 Subject: [PATCH 177/333] [splittiming] Helper function won't work here. Not counting #TICKCOUNTS and #COMBOS interactions... I think the loader is good. --- src/NotesLoaderSMA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 2d17557deb..5f4d2faea4 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -538,7 +538,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else { state = SMA_GETTING_STEP_INFO; - pNewNotes = out.CreateSteps(); + pNewNotes = new Steps; } } From b5129ac163f19d74947a51974bae104dcdc0ff26 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 19:53:57 -0500 Subject: [PATCH 178/333] [Banner] Added ScrollMode and ScrollSortOrder metrics. --- Docs/Changelog_sm5.txt | 1 + Themes/_fallback/metrics.ini | 2 ++ src/Banner.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 94335c16d0..605c20658e 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -12,6 +12,7 @@ StepMania 5.0 $NEXT | 20110xyy ---------- * [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] * [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] +* [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] 2011/05/11 ---------- diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index cd36f351cc..f804a18e50 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -220,6 +220,8 @@ BottomEdge=SCREEN_BOTTOM # Scroll stuff when you roll over it, DDR Extreme style. ScrollRandom=false ScrollRoulette=false +ScrollMode=false +ScrollScrollOrder=false # Control how fast the banner scrolls. Higher numbers mean slower. ScrollSpeedDivisor=2 diff --git a/src/Banner.cpp b/src/Banner.cpp index b8d115e206..f78777d73d 100644 --- a/src/Banner.cpp +++ b/src/Banner.cpp @@ -17,8 +17,8 @@ REGISTER_ACTOR_CLASS( Banner ); ThemeMetric SCROLL_RANDOM ("Banner","ScrollRandom"); ThemeMetric SCROLL_ROULETTE ("Banner","ScrollRoulette"); -//ThemeMetric SCROLL_MODE ("Banner","ScrollMode"); -//ThemeMetric SCROLL_SORT_ORDER ("Banner","ScrollSortOrder"); +ThemeMetric SCROLL_MODE ("Banner","ScrollMode"); +ThemeMetric SCROLL_SORT_ORDER ("Banner","ScrollSortOrder"); ThemeMetric SCROLL_SPEED_DIVISOR ("Banner","ScrollSpeedDivisor"); Banner::Banner() @@ -119,7 +119,7 @@ void Banner::LoadFromSong( Song* pSong ) // NULL means no song void Banner::LoadMode() { Load( THEME->GetPathG("Banner","Mode") ); - m_bScrolling = false; + m_bScrolling = (bool)SCROLL_MODE; } void Banner::LoadFromSongGroup( RString sSongGroup ) @@ -229,7 +229,7 @@ void Banner::LoadFromSortOrder( SortOrder so ) if( so != SORT_GROUP && so != SORT_RECENT ) Load( THEME->GetPathG("Banner",ssprintf("%s",SortOrderToString(so).c_str())) ); } - m_bScrolling = false; + m_bScrolling = (bool)SCROLL_SORT_ORDER; } // lua start From 78681a52ff1d169e45dabd7b7aa1c5087e682d90 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 20:30:44 -0500 Subject: [PATCH 179/333] fix typo --- Themes/_fallback/metrics.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index f804a18e50..280fb4d344 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -221,7 +221,7 @@ BottomEdge=SCREEN_BOTTOM ScrollRandom=false ScrollRoulette=false ScrollMode=false -ScrollScrollOrder=false +ScrollSortOrder=false # Control how fast the banner scrolls. Higher numbers mean slower. ScrollSpeedDivisor=2 From 62964d08ffceebc863ada6c9ce05130f8d91a931 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:06:14 -0500 Subject: [PATCH 180/333] make these two asserts more helpful --- src/ScoreKeeperNormal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index b3e106bfaf..3a024ec348 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -360,14 +360,14 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score ) } - ASSERT( iScore >= 0 ); + ASSERT_M( iScore >= 0, "iScore < 0 before re-rounding" ); // Undo rounding from the last tap, and re-round. iScore += m_iScoreRemainder; m_iScoreRemainder = (iScore % m_iRoundTo); iScore = iScore - m_iScoreRemainder; - ASSERT( iScore >= 0 ); + ASSERT_M( iScore >= 0, "iScore < 0 after re-rounding" ); // LOG->Trace( "score: %i", iScore ); } From e4a446482441cb78fb8c9331e849f152830cb6ba Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:18:14 -0500 Subject: [PATCH 181/333] [StepsDisplay] Added MeterFormatString metric. --- Docs/Changelog_sm5.txt | 1 + Themes/_fallback/metrics.ini | 2 ++ src/StepsDisplay.cpp | 4 ++-- src/StepsDisplay.h | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 605c20658e..f0e3a0f295 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -10,6 +10,7 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/14 ---------- +* [StepsDisplay] Added MeterFormatString metric. [AJ] * [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] * [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] * [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 280fb4d344..298794735b 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1286,6 +1286,7 @@ TicksSetCommand= # ShowMeter=false ZeroMeterString="0" +MeterFormatString="%i" MeterX=0 MeterY=0 MeterOnCommand= @@ -2009,6 +2010,7 @@ TicksOnCommand=shadowlength,0; TicksSetCommand=%function(self,param) self:diffuse(CustomDifficultyToColor(param.CustomDifficulty)) if param.Meter > 9 then self:glowshift() else self:stopeffect() end end ShowTicks=false ShowMeter=true +MeterFormatString="%i" ZeroMeterString="?" MeterX=30 MeterY=0 diff --git a/src/StepsDisplay.cpp b/src/StepsDisplay.cpp index a42fb31831..7df5e6b930 100644 --- a/src/StepsDisplay.cpp +++ b/src/StepsDisplay.cpp @@ -59,6 +59,7 @@ void StepsDisplay::Load( const RString &sMetricsGroup, const PlayerState *pPlaye m_bShowAutogen.Load(m_sMetricsGroup,"ShowAutogen"); m_bShowStepsType.Load(m_sMetricsGroup,"ShowStepsType"); m_sZeroMeterString.Load(m_sMetricsGroup,"ZeroMeterString"); + m_sMeterFormatString.Load(m_sMetricsGroup,"MeterFormatString"); m_sprFrame.Load( THEME->GetPathG(m_sMetricsGroup,"frame") ); m_sprFrame->SetName( "Frame" ); @@ -241,8 +242,7 @@ void StepsDisplay::SetInternal( const SetParams ¶ms ) } else { - // todo: allow themer to specify a format string? -aj - const RString sMeter = ssprintf( "%i", params.iMeter ); + const RString sMeter = ssprintf( m_sMeterFormatString.GetValue().c_str(), params.iMeter ); m_textMeter.SetText( sMeter ); m_textMeter.HandleMessage( msg ); } diff --git a/src/StepsDisplay.h b/src/StepsDisplay.h index ee266aace6..c3af3063a9 100644 --- a/src/StepsDisplay.h +++ b/src/StepsDisplay.h @@ -72,6 +72,7 @@ private: ThemeMetric m_bShowAutogen; ThemeMetric m_bShowStepsType; ThemeMetric m_sZeroMeterString; + ThemeMetric m_sMeterFormatString; }; #endif From d006795311d52fe4622fe7a5c101648b9ebdd909 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:27:46 -0500 Subject: [PATCH 182/333] hopeful autoplay score saving fix --- src/StageStats.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/StageStats.cpp b/src/StageStats.cpp index df3a500349..d30e7bfe9f 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -202,7 +202,6 @@ void StageStats::FinalizeScores( bool bSummary ) m_multiPlayer[mp].m_HighScore = FillInHighScore( m_multiPlayer[mp], *GAMESTATE->m_pMultiPlayerState[mp], "", sPlayerGuid ); } - // todo: don't save scores in autoplay -aj FOREACH_HumanPlayer( p ) { const HighScore &hs = m_player[p].m_HighScore; @@ -215,6 +214,10 @@ void StageStats::FinalizeScores( bool bSummary ) if( hs.GetDisqualified() ) continue; + // Don't save autoplay scores + if( m_bUsedAutoplay ) + continue; + if( bSummary ) { // don't save scores if any stage was failed From dc143c58e6bda9a8b2dd4e18ef98cbe9ac8d30e0 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:30:32 -0500 Subject: [PATCH 183/333] remove out of date comment, overlay/underlay aren't going anywhere as they're needed to abuse custom menus --- src/ScreenWithMenuElements.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ScreenWithMenuElements.cpp b/src/ScreenWithMenuElements.cpp index df4f78ca95..8377a5fb75 100644 --- a/src/ScreenWithMenuElements.cpp +++ b/src/ScreenWithMenuElements.cpp @@ -64,10 +64,6 @@ void ScreenWithMenuElements::Init() this->AddChild( m_MenuTimer ); } - /* TODO: Remove overlay and underlay in favor of more flexible decorations */ - // Decorations don't let you use UpdateCommand, so don't ever - // remove underlay and overlay, otherwise good themes break. -aj - m_sprUnderlay.Load( THEME->GetPathB(m_sName,"underlay") ); m_sprUnderlay->SetName("Underlay"); m_sprUnderlay->SetDrawOrder( DRAW_ORDER_UNDERLAY ); From afaa711038b5370c3c28f7019d2e7526baf1da90 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:41:32 -0500 Subject: [PATCH 184/333] [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand doesn't set a screen. --- Docs/Changelog_sm5.txt | 2 ++ src/ScreenSelectMaster.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index f0e3a0f295..9ad6035da8 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -10,6 +10,8 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/14 ---------- +* [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand + doesn't set a screen. [AJ] * [StepsDisplay] Added MeterFormatString metric. [AJ] * [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] * [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] diff --git a/src/ScreenSelectMaster.cpp b/src/ScreenSelectMaster.cpp index 83276d4e33..0e50f5ccbf 100644 --- a/src/ScreenSelectMaster.cpp +++ b/src/ScreenSelectMaster.cpp @@ -812,8 +812,9 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input ) mc.ApplyToAllPlayers(); // We want to be able to broadcast a Start message to the theme, in // case a themer wants to handle something. -aj - // TODO: Add a param to differentiate this from the message below. - MESSAGEMAN->Broadcast( (MessageID)(Message_MenuStartP1+pn) ); + Message msg( MessageIDToString((MessageID)(Message_MenuStartP1+pn)) ); + msg.SetParam( "ScreenEmpty", true ); + MESSAGEMAN->Broadcast( msg ); return; } From f1bc24160ba01176c2346b8183238afb2d01905d Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:41:57 -0500 Subject: [PATCH 185/333] remove old note, reorganize dead code slightly --- src/ScreenSelectMusic.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index fe4aee3aab..eb3acff4d9 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1455,7 +1455,9 @@ void ScreenSelectMusic::MenuBack( const InputEventPlus &input ) // Handle unselect song (ffff) // todo: this isn't right at all. -aj /* - if( m_SelectionState == SelectionState_SelectingSteps && !m_bStepsChosen[input.pn] && input.MenuI == GAME_BUTTON_BACK && input.type == IET_FIRST_PRESS ) + if( m_SelectionState == SelectionState_SelectingSteps && + !m_bStepsChosen[input.pn] && input.MenuI == GAME_BUTTON_BACK && + input.type == IET_FIRST_PRESS ) { // if a player has chosen their steps already, don't unchoose song. FOREACH_HumanPlayer( p ) @@ -1530,7 +1532,6 @@ void ScreenSelectMusic::AfterStepsOrTrailChange( const vector &vpn else { // The numbers shouldn't stay if the current selection is NULL. - // todo: Let themers set the text value instead of just using 0. -aj m_textHighScore[pn].SetText( NULL_SCORE_STRING ); } } From 87148206a7bbd17c6056ea9b333da6b836b6d2cc Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:58:42 -0500 Subject: [PATCH 186/333] [ModIcon] Added StopWords metric. --- Docs/Changelog_sm5.txt | 1 + Themes/_fallback/metrics.ini | 1 + src/ModIcon.cpp | 9 +++++---- src/ModIcon.h | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 9ad6035da8..daf91cd16f 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -10,6 +10,7 @@ StepMania 5.0 $NEXT | 20110xyy 2011/05/14 ---------- +* [ModIcon] Added StopWords metric. [AJ] * [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand doesn't set a screen. [AJ] * [StepsDisplay] Added MeterFormatString metric. [AJ] diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 298794735b..1b23a2200c 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -4036,6 +4036,7 @@ TextX=0 TextY=0 TextOnCommand=maxwidth,40;uppercase,true;shadowlength,0;diffuse,color("#f6ff00") CropTextToWidth=50 +StopWords="1X,default,Overhead,Off" [ModIconSelectMusic] Fallback="ModIcon" diff --git a/src/ModIcon.cpp b/src/ModIcon.cpp index 0ef95daeb4..9dcf9dd929 100644 --- a/src/ModIcon.cpp +++ b/src/ModIcon.cpp @@ -40,11 +40,9 @@ void ModIcon::Load( RString sMetricsGroup ) CROP_TEXT_TO_WIDTH.Load( sMetricsGroup, "CropTextToWidth" ); // stop words - /* STOP_WORDS.Load( sMetricsGroup, "StopWords" ); m_vStopWords.empty(); split(STOP_WORDS, ",", m_vStopWords); - */ Set(""); } @@ -54,6 +52,7 @@ void ModIcon::Set( const RString &_sText ) RString sText = _sText; // todo: make these metricable -aj + /* static const RString sStopWords[] = { "1X", @@ -61,9 +60,11 @@ void ModIcon::Set( const RString &_sText ) "OVERHEAD", "OFF", }; + */ - for( unsigned i=0; i CROP_TEXT_TO_WIDTH; + ThemeMetric STOP_WORDS; + vector m_vStopWords; }; #endif From 250bd08f99efd93276cd9442037fdc497e88efd9 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 22:59:16 -0500 Subject: [PATCH 187/333] pedantic changes --- src/ModIcon.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/ModIcon.cpp b/src/ModIcon.cpp index 9dcf9dd929..6d359046e7 100644 --- a/src/ModIcon.cpp +++ b/src/ModIcon.cpp @@ -39,6 +39,7 @@ void ModIcon::Load( RString sMetricsGroup ) this->AddChild( &m_text ); CROP_TEXT_TO_WIDTH.Load( sMetricsGroup, "CropTextToWidth" ); + // stop words STOP_WORDS.Load( sMetricsGroup, "StopWords" ); m_vStopWords.empty(); @@ -51,18 +52,6 @@ void ModIcon::Set( const RString &_sText ) { RString sText = _sText; - // todo: make these metricable -aj - /* - static const RString sStopWords[] = - { - "1X", - "DEFAULT", - "OVERHEAD", - "OFF", - }; - */ - - //for( unsigned i=0; i Date: Sun, 15 May 2011 00:09:44 -0400 Subject: [PATCH 188/333] [splittiming] Revert Song Timing Restrictions. I still think BG Changes should be Song Timing only though. --- Themes/_fallback/Languages/en.ini | 4 -- src/ScreenEdit.cpp | 90 ++++++++----------------------- 2 files changed, 22 insertions(+), 72 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index beb4ac939d..5221f213de 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1259,11 +1259,7 @@ This change creates more than %d notes in a measure.=This change creates more th This change creates notes past the end of the music and is not allowed.=This change creates notes past the end of the music and is not allowed. This will destroy all unsaved changes.=This will destroy all unsaved changes. Undo=Undo -You must be in Step Timing Mode to edit the notes.=You must be in Step Timing Mode to edit the notes. You must be in Song Timing Mode to edit BG Changes.=You must be in Song Timing Mode to edit BG Changes. -You must be in Step Timing Mode to record steps.=You must be in Step Timing Mode to record steps. -You must be in Step Timing Mode to insert beats and shift down.=You must be in Step Timing Mode to insert beats and shift down. -You must be in Step Timing Mode to delete beats and shift up.=You must be in Step Timing Mode to delete beats and shift up. Current beat=Current beat Current second=Current second diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index e6d2b477e8..38ff20c18a 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -995,7 +995,7 @@ void ScreenEdit::Update( float fDeltaTime ) } float fLastBeat = NoteRowToBeat(m_iStopPlayingAt); - if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING && GAMESTATE->m_bIsEditorStepTiming ) + if( bButtonIsBeingPressed && m_EditState == STATE_RECORDING ) { float fSeconds = m_pSteps->m_Timing.GetElapsedTimeFromBeat( fLastBeat ); fLastBeat = m_pSteps->m_Timing.GetBeatFromElapsedTime( fSeconds + 0.5f ); @@ -1280,11 +1280,7 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime ) return -1; } -static LocalizedString TAP_NOTE_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to edit the notes." ); static LocalizedString BG_CHANGE_STEP_TIMING ( "ScreenEdit", "You must be in Song Timing Mode to edit BG Changes." ); -static LocalizedString RECORD_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to record steps." ); -static LocalizedString INSERT_BEAT_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to insert beats and shift down." ); -static LocalizedString DELETE_BEAT_SONG_TIMING ( "ScreenEdit", "You must be in Step Timing Mode to delete beats and shift up." ); static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" ); static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" ); @@ -1316,15 +1312,6 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( input.type != IET_FIRST_PRESS ) break; // We only care about first presses - - if( !GAMESTATE->m_bIsEditorStepTiming ) - { - // Only allow steps to be hit in Step Timing. - SCREENMAN->SystemMessage( TAP_NOTE_SONG_TIMING ); - SCREENMAN->PlayInvalidSound(); - break; - } - int iCol = EditB - EDIT_BUTTON_COLUMN_0; @@ -1555,20 +1542,18 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) { // update enabled/disabled in g_AreaMenu bool bAreaSelected = m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1; - g_AreaMenu.rows[cut].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[cut].bEnabled = bAreaSelected; g_AreaMenu.rows[copy].bEnabled = bAreaSelected; - g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty() && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1 && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[clear].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[quantize].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[turn].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[transform].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[alter].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty(); + g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1; + g_AreaMenu.rows[clear].bEnabled = bAreaSelected; + g_AreaMenu.rows[quantize].bEnabled = bAreaSelected; + g_AreaMenu.rows[turn].bEnabled = bAreaSelected; + g_AreaMenu.rows[transform].bEnabled = bAreaSelected; + g_AreaMenu.rows[alter].bEnabled = bAreaSelected; g_AreaMenu.rows[tempo].bEnabled = bAreaSelected; g_AreaMenu.rows[play].bEnabled = bAreaSelected; - g_AreaMenu.rows[record].bEnabled = bAreaSelected && GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[insert_and_shift].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_AreaMenu.rows[delete_and_shift].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_AreaMenu.rows[record].bEnabled = bAreaSelected; g_AreaMenu.rows[convert_to_pause].bEnabled = bAreaSelected; g_AreaMenu.rows[undo].bEnabled = m_bHasUndo; EditMiniMenu( &g_AreaMenu, SM_BackFromAreaMenu ); @@ -2083,12 +2068,6 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) HandleMainMenuChoice( play_selection ); break; case EDIT_BUTTON_RECORD_SELECTION: - if( !GAMESTATE->m_bIsEditorStepTiming ) - { - SCREENMAN->SystemMessage( RECORD_SONG_TIMING ); - SCREENMAN->PlayInvalidSound(); - break; - } if( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 ) { HandleAreaMenuChoice( record ); @@ -2125,14 +2104,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_INSERT: - if( GAMESTATE->m_bIsEditorStepTiming ) - { - HandleAreaMenuChoice( insert_and_shift ); - } - else - { - SCREENMAN->SystemMessage( INSERT_BEAT_SONG_TIMING ); - } + HandleAreaMenuChoice( insert_and_shift ); SCREENMAN->PlayInvalidSound(); break; @@ -2142,14 +2114,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_DELETE: - if( GAMESTATE->m_bIsEditorStepTiming ) - { - HandleAreaMenuChoice( delete_and_shift ); - } - else - { - SCREENMAN->SystemMessage( DELETE_BEAT_SONG_TIMING ); - } + HandleAreaMenuChoice( delete_and_shift ); SCREENMAN->PlayInvalidSound(); break; @@ -2190,9 +2155,6 @@ void ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB ) TransitionEditState( STATE_EDITING ); return; } - - if ( !GAMESTATE->m_bIsEditorStepTiming ) - return; // can't allow changes if in song timing. if( input.pn != PLAYER_1 ) return; // ignore @@ -2259,12 +2221,7 @@ void ScreenEdit::InputRecordPaused( const InputEventPlus &input, EditButton Edit break; case EDIT_BUTTON_RECORD_SELECTION: - if( GAMESTATE->m_bIsEditorStepTiming ) - TransitionEditState( STATE_RECORDING ); - else - { - // broadcast error maybe. - } + TransitionEditState( STATE_RECORDING ); break; case EDIT_BUTTON_RECORD_FROM_CURSOR: @@ -2612,20 +2569,17 @@ void ScreenEdit::ScrollTo( float fDestinationBeat ) if( !EditIsBeingPressed(b) ) continue; - if( GAMESTATE->m_bIsEditorStepTiming ) - { - // create a new hold note - int iStartRow = BeatToNoteRow( min(fOriginalBeat, fDestinationBeat) ); - int iEndRow = BeatToNoteRow( max(fOriginalBeat, fDestinationBeat) ); + // create a new hold note + int iStartRow = BeatToNoteRow( min(fOriginalBeat, fDestinationBeat) ); + int iEndRow = BeatToNoteRow( max(fOriginalBeat, fDestinationBeat) ); - // Don't SaveUndo. We want to undo the whole hold, not just the last segment - // that the user made. Dragging the hold bigger can only absorb and remove - // other taps, so dragging won't cause us to exceed the note limit. - TapNote tn = EditIsBeingPressed(EDIT_BUTTON_LAY_ROLL) ? TAP_ORIGINAL_ROLL_HEAD : TAP_ORIGINAL_HOLD_HEAD; + // Don't SaveUndo. We want to undo the whole hold, not just the last segment + // that the user made. Dragging the hold bigger can only absorb and remove + // other taps, so dragging won't cause us to exceed the note limit. + TapNote tn = EditIsBeingPressed(EDIT_BUTTON_LAY_ROLL) ? TAP_ORIGINAL_ROLL_HEAD : TAP_ORIGINAL_HOLD_HEAD; - tn.pn = m_InputPlayerNumber; - m_NoteDataEdit.AddHoldNote( iCol, iStartRow, iEndRow, tn ); - } + tn.pn = m_InputPlayerNumber; + m_NoteDataEdit.AddHoldNote( iCol, iStartRow, iEndRow, tn ); } if( EditIsBeingPressed(EDIT_BUTTON_SCROLL_SELECT) ) From 0922df6d51ca5db64837cb568c974626308d06d9 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 23:36:42 -0500 Subject: [PATCH 189/333] handle WM_MOUSEWHEEL message in GraphicsWindow_WndProc --- src/archutils/Win32/GraphicsWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/archutils/Win32/GraphicsWindow.cpp b/src/archutils/Win32/GraphicsWindow.cpp index 814afa882a..cb2b128d71 100644 --- a/src/archutils/Win32/GraphicsWindow.cpp +++ b/src/archutils/Win32/GraphicsWindow.cpp @@ -136,6 +136,7 @@ static LRESULT CALLBACK GraphicsWindow_WndProc( HWND hWnd, UINT msg, WPARAM wPar case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: + case WM_MOUSEWHEEL: // We handle all input ourself, via DirectInput. return 0; From fcdd5bcddd80d6f7e98e9ba0e676a9a8ed18ebea Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 14 May 2011 23:49:32 -0500 Subject: [PATCH 190/333] cleanup --- src/ModIconRow.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ModIconRow.h b/src/ModIconRow.h index 09654142d0..47c8a94ad8 100644 --- a/src/ModIconRow.h +++ b/src/ModIconRow.h @@ -22,9 +22,7 @@ public: virtual void HandleMessage( const Message &msg ); - // // Commands - // virtual void PushSelf( lua_State *L ); protected: From 83ba698ced1c04bb119cbae19d64491fd3f3e7e4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 00:57:01 -0400 Subject: [PATCH 191/333] [splittiming] This TODO seems obsolete. --- src/SongPosition.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SongPosition.h b/src/SongPosition.h index 56cf0e38d5..9ca7bbe778 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -15,7 +15,6 @@ class SongPosition // Arcade - the current stage (one song). // Oni/Endless - a single song in a course. // Let a lot of classes access this info here so they don't have to keep their own copies. - // todo: [NUM_PLAYERS] this for split bpm lolol -aj float m_fMusicSeconds; // time into the current song, not scaled by music rate float m_fSongBeat; float m_fSongBeatNoOffset; From d99e7b5c5b80a6358b369455642fea82b3ca2c8e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 00:57:35 -0400 Subject: [PATCH 192/333] [splittiming] Re-establish Actor code. --- src/Actor.cpp | 21 +++++++++++++++++++-- src/Actor.h | 6 ++++++ src/GameState.cpp | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 72a3ee3856..3191d98d56 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -34,6 +34,8 @@ REGISTER_ACTOR_CLASS_WITH_NAME( HiddenActor, Actor ); float Actor::g_fCurrentBGMTime = 0, Actor::g_fCurrentBGMBeat; float Actor::g_fCurrentBGMTimeNoOffset = 0, Actor::g_fCurrentBGMBeatNoOffset = 0; +vector Actor::g_vfCurrentBGMBeatPlayer(NUM_PlayerNumber, 0); +vector Actor::g_vfCurrentBGMBeatPlayerNoOffset(NUM_PlayerNumber, 0); Actor *Actor::Copy() const { return new Actor(*this); } @@ -68,6 +70,12 @@ void Actor::SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBe g_fCurrentBGMBeatNoOffset = fBeatNoOffset; } +void Actor::SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ) +{ + g_vfCurrentBGMBeatPlayer[pn] = fBeat; + g_vfCurrentBGMBeatPlayerNoOffset[pn] = fBeatNoOffset; +} + void Actor::SetBGMLight( int iLightNumber, float fCabinetLights ) { ASSERT( iLightNumber < NUM_CabinetLight ); @@ -150,8 +158,7 @@ Actor::Actor() lua_setfield( L, -2, "ctx" ); lua_pop( L, 1 ); LUA->Release( L ); - - + m_size = RageVector2( 1, 1 ); InitState(); m_pParent = NULL; @@ -676,6 +683,16 @@ void Actor::UpdateInternal( float fDeltaTime ) m_fSecsIntoEffect = g_fCurrentBGMBeat; break; + case CLOCK_BGM_BEAT_PLAYER1: + m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_1] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayerNoOffset[PLAYER_1]; + break; + + case CLOCK_BGM_BEAT_PLAYER2: + m_fEffectDelta = g_vfCurrentBGMBeatPlayer[PLAYER_2] - m_fSecsIntoEffect; + m_fSecsIntoEffect = g_vfCurrentBGMBeatPlayerNoOffset[PLAYER_2]; + break; + case CLOCK_BGM_TIME: m_fEffectDelta = g_fCurrentBGMTime - m_fSecsIntoEffect; m_fSecsIntoEffect = g_fCurrentBGMTime; diff --git a/src/Actor.h b/src/Actor.h index 45d080dabe..919d4994f7 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -1,6 +1,7 @@ #ifndef ACTOR_H #define ACTOR_H +#include "PlayerNumber.h" #include "RageTypes.h" #include "RageUtil_AutoPtr.h" #include "LuaReference.h" @@ -109,6 +110,7 @@ public: virtual void LoadFromNode( const XNode* pNode ); static void SetBGMTime( float fTime, float fBeat, float fTimeNoOffset, float fBeatNoOffset ); + static void SetPlayerBGMBeat( PlayerNumber pn, float fBeat, float fBeatNoOffset ); static void SetBGMLight( int iLightNumber, float fCabinetLights ); /** @@ -131,6 +133,8 @@ public: CLOCK_BGM_BEAT, CLOCK_BGM_TIME_NO_OFFSET, CLOCK_BGM_BEAT_NO_OFFSET, + CLOCK_BGM_BEAT_PLAYER1, + CLOCK_BGM_BEAT_PLAYER2, CLOCK_LIGHT_1 = 1000, CLOCK_LIGHT_LAST = 1100, NUM_CLOCKS @@ -713,6 +717,8 @@ protected: // global state static float g_fCurrentBGMTime, g_fCurrentBGMBeat; static float g_fCurrentBGMTimeNoOffset, g_fCurrentBGMBeatNoOffset; + static vector g_vfCurrentBGMBeatPlayer; + static vector g_vfCurrentBGMBeatPlayerNoOffset; private: // commands diff --git a/src/GameState.cpp b/src/GameState.cpp index abb3c63552..8205d4143f 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -953,7 +953,7 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti if( m_pCurSteps[pn] ) { m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, m_pCurSteps[pn]->m_Timing, timestamp ); - // Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); + Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); } } } From c8b3a1338b1e4d0e25e43ed4dd4795c09169d898 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 00:01:38 -0500 Subject: [PATCH 193/333] mouse input is working slightly better... --- .../InputHandler/InputHandler_DirectInput.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/arch/InputHandler/InputHandler_DirectInput.cpp b/src/arch/InputHandler/InputHandler_DirectInput.cpp index a0a9316e64..4fb78dee35 100644 --- a/src/arch/InputHandler/InputHandler_DirectInput.cpp +++ b/src/arch/InputHandler/InputHandler_DirectInput.cpp @@ -529,11 +529,28 @@ void InputHandler_DInput::UpdateBuffered( DIDevice &device, const RageTimer &tm INPUTFILTER->UpdateMouseWheel(l); { up = MOUSE_WHEELUP; down = MOUSE_WHEELDOWN; - l = SCALE( int(evtbuf[i].dwData), -WHEEL_DELTA, WHEEL_DELTA, 1.0f, -1.0f ); - DeviceInput diUp = DeviceInput(dev, up, max(-l,0), tm); - DeviceInput diDown = DeviceInput(dev, down, max(+l,0), tm); - ButtonPressed( diUp ); - ButtonPressed( diDown ); + //l = SCALE( int(evtbuf[i].dwData), -WHEEL_DELTA, WHEEL_DELTA, 1.0f, -1.0f ); + if( int(evtbuf[i].dwData) > 0 ) + { + DeviceInput diUp = DeviceInput(dev, up, 1, tm); + ButtonPressed( diUp ); + DeviceInput diDown = DeviceInput(dev, down, 0, tm); + ButtonPressed( diDown ); + } + else if( int(evtbuf[i].dwData) < 0 ) + { + DeviceInput diDown = DeviceInput(dev, down, 1, tm); + ButtonPressed( diDown ); + DeviceInput diUp = DeviceInput(dev, up, 0, tm); + ButtonPressed( diUp ); + } + else + { + DeviceInput diUp = DeviceInput(dev, up, 0, tm); + ButtonPressed( diUp ); + DeviceInput diDown = DeviceInput(dev, down, 0, tm); + ButtonPressed( diDown ); + } } break; default: LOG->MapLog( "unknown input", From 2724e35e971b44785cbdb43c78bae3063c59e69d Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 00:01:45 -0500 Subject: [PATCH 194/333] commenting --- src/archutils/Win32/GraphicsWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/archutils/Win32/GraphicsWindow.cpp b/src/archutils/Win32/GraphicsWindow.cpp index cb2b128d71..44314367e0 100644 --- a/src/archutils/Win32/GraphicsWindow.cpp +++ b/src/archutils/Win32/GraphicsWindow.cpp @@ -136,7 +136,7 @@ static LRESULT CALLBACK GraphicsWindow_WndProc( HWND hWnd, UINT msg, WPARAM wPar case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: - case WM_MOUSEWHEEL: + case WM_MOUSEWHEEL: // might want to use this for GET_WHEEL_DELTA_WPARAM(wParam) -aj // We handle all input ourself, via DirectInput. return 0; From 84e93b0bbd6030c4b2ee57e4c3752d6ce236cd0a Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 00:09:44 -0500 Subject: [PATCH 195/333] update polled mousewheel code --- .../InputHandler/InputHandler_DirectInput.cpp | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/arch/InputHandler/InputHandler_DirectInput.cpp b/src/arch/InputHandler/InputHandler_DirectInput.cpp index 4fb78dee35..3dc80a0717 100644 --- a/src/arch/InputHandler/InputHandler_DirectInput.cpp +++ b/src/arch/InputHandler/InputHandler_DirectInput.cpp @@ -417,17 +417,24 @@ void InputHandler_DInput::UpdatePolled( DIDevice &device, const RageTimer &tm ) val = state.lZ; //LOG->Trace("MouseWheel polled: %i",val); INPUTFILTER->UpdateMouseWheel(val); - - /* - if( (int)val != 0 ) + if( val == 0 ) + { + // release all + ButtonPressed( DeviceInput(dev, pos, 0, tm) ); + ButtonPressed( DeviceInput(dev, neg, 0, tm) ); + } + else if( int(val) > 0 ) { // positive values: WheelUp + ButtonPressed( DeviceInput(dev, pos, 1, tm) ); + ButtonPressed( DeviceInput(dev, neg, 0, tm) ); + } + else if( int(val) < 0 ) + { // negative values: WheelDown - float l = SCALE( int(val), -120.0f, 120.0f, -1.0f, 1.0f ); - ButtonPressed( DeviceInput(dev, neg, max(-l,0), tm) ); - ButtonPressed( DeviceInput(dev, pos, max(+l,0), tm) ); + ButtonPressed( DeviceInput(dev, neg, 1, tm) ); + ButtonPressed( DeviceInput(dev, pos, 0, tm) ); } - */ } break; default: LOG->MapLog( "unknown input", @@ -532,23 +539,23 @@ void InputHandler_DInput::UpdateBuffered( DIDevice &device, const RageTimer &tm //l = SCALE( int(evtbuf[i].dwData), -WHEEL_DELTA, WHEEL_DELTA, 1.0f, -1.0f ); if( int(evtbuf[i].dwData) > 0 ) { - DeviceInput diUp = DeviceInput(dev, up, 1, tm); + DeviceInput diUp = DeviceInput(dev, up, 1.0f, tm); ButtonPressed( diUp ); - DeviceInput diDown = DeviceInput(dev, down, 0, tm); + DeviceInput diDown = DeviceInput(dev, down, 0.0f, tm); ButtonPressed( diDown ); } else if( int(evtbuf[i].dwData) < 0 ) { - DeviceInput diDown = DeviceInput(dev, down, 1, tm); + DeviceInput diDown = DeviceInput(dev, down, 1.0f, tm); ButtonPressed( diDown ); - DeviceInput diUp = DeviceInput(dev, up, 0, tm); + DeviceInput diUp = DeviceInput(dev, up, 0.0f, tm); ButtonPressed( diUp ); } else { - DeviceInput diUp = DeviceInput(dev, up, 0, tm); + DeviceInput diUp = DeviceInput(dev, up, 0.0f, tm); ButtonPressed( diUp ); - DeviceInput diDown = DeviceInput(dev, down, 0, tm); + DeviceInput diDown = DeviceInput(dev, down, 0.0f, tm); ButtonPressed( diDown ); } } From 376ab3d66f0020b923e15c163f90c19d9fff4e62 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 00:33:39 -0500 Subject: [PATCH 196/333] more changes to mousewheel code; still not working properly --- .../InputHandler/InputHandler_DirectInput.cpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/arch/InputHandler/InputHandler_DirectInput.cpp b/src/arch/InputHandler/InputHandler_DirectInput.cpp index 3dc80a0717..9817a88d0d 100644 --- a/src/arch/InputHandler/InputHandler_DirectInput.cpp +++ b/src/arch/InputHandler/InputHandler_DirectInput.cpp @@ -536,20 +536,31 @@ void InputHandler_DInput::UpdateBuffered( DIDevice &device, const RageTimer &tm INPUTFILTER->UpdateMouseWheel(l); { up = MOUSE_WHEELUP; down = MOUSE_WHEELDOWN; + float fWheelDelta = l; //l = SCALE( int(evtbuf[i].dwData), -WHEEL_DELTA, WHEEL_DELTA, 1.0f, -1.0f ); - if( int(evtbuf[i].dwData) > 0 ) + if( l > 0 ) { DeviceInput diUp = DeviceInput(dev, up, 1.0f, tm); - ButtonPressed( diUp ); DeviceInput diDown = DeviceInput(dev, down, 0.0f, tm); - ButtonPressed( diDown ); + while( fWheelDelta >= WHEEL_DELTA ) + { + ButtonPressed( diUp ); + ButtonPressed( diDown ); + INPUTFILTER->UpdateMouseWheel(fWheelDelta); + fWheelDelta -= WHEEL_DELTA; + } } - else if( int(evtbuf[i].dwData) < 0 ) + else if( l < 0 ) { DeviceInput diDown = DeviceInput(dev, down, 1.0f, tm); - ButtonPressed( diDown ); DeviceInput diUp = DeviceInput(dev, up, 0.0f, tm); - ButtonPressed( diUp ); + while( fWheelDelta <= -WHEEL_DELTA ) + { + ButtonPressed( diDown ); + ButtonPressed( diUp ); + INPUTFILTER->UpdateMouseWheel(fWheelDelta); + fWheelDelta += WHEEL_DELTA; + } } else { From 728a317a909ddd1d9d6972314d0696c886fd9921 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 03:17:30 -0500 Subject: [PATCH 197/333] thinking of how to expose this to Lua... --- src/ModIconRow.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ModIconRow.cpp b/src/ModIconRow.cpp index aae4517466..362c5a8e4d 100644 --- a/src/ModIconRow.cpp +++ b/src/ModIconRow.cpp @@ -66,10 +66,35 @@ void ModIconRow::HandleMessage( const Message &msg ) struct OptionColumnEntry { - char szString[30]; + char *szString; int iSlotIndex; + + //void FromStack( lua_State *L, int iPos ); }; +/* +void OptionColumnEntry::FromStack( lua_State *L, int iPos ) +{ + if( lua_type(L, iPos) != LUA_TTABLE ) + return; + + lua_pushvalue( L, iPos ); + const int iTab = lua_gettop( L ); + + // option name + lua_getfield( L, iTab, "Name" ); + RString sName = lua_tostring( L, -1 ); + szString = const_cast(sName.c_str()); + lua_settop( L, iTab ); + + // option icon index + lua_getfield( L, iTab, "IconIndex" ); + iSlotIndex = lua_tointeger( L, -1 ); + lua_settop( L, iTab ); +} +static vector g_OptionColumnEntries; +*/ + // todo: metric these? -aj static const OptionColumnEntry g_OptionColumnEntries[] = { From 8f70dcf99bfb464523f308e6d0a11c5d94c96c9a Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 03:18:34 -0500 Subject: [PATCH 198/333] move DwiCompatibleStringToDifficulty from Difficulty to NotesLoaderDWI; make .sm and .sm-derived formats use DifficultyToString since NotesWriterSM/SMA/SSC should be writing normalized strings --- src/Difficulty.cpp | 29 ----------------------------- src/Difficulty.h | 2 -- src/NotesLoaderDWI.cpp | 28 ++++++++++++++++++++++++++++ src/NotesLoaderSM.cpp | 2 +- src/NotesLoaderSMA.cpp | 2 +- src/NotesLoaderSSC.cpp | 4 ++-- 6 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/Difficulty.cpp b/src/Difficulty.cpp index 9e64fe665b..e37c5a4745 100644 --- a/src/Difficulty.cpp +++ b/src/Difficulty.cpp @@ -21,35 +21,6 @@ XToString( Difficulty ); StringToX( Difficulty ); LuaXType( Difficulty ); -/* We prefer the above names; recognize a number of others, too. (They'll get - * normalized when written to SMs, etc.) TODO: Format specific hacks should be - * moved into the file loader for that format. We don't want to carry these - * hacks forward to file formats that don't need them. */ -Difficulty DwiCompatibleStringToDifficulty( const RString& sDC ) -{ - RString s2 = sDC; - s2.MakeLower(); - if( s2 == "beginner" ) return Difficulty_Beginner; - else if( s2 == "easy" ) return Difficulty_Easy; - else if( s2 == "basic" ) return Difficulty_Easy; - else if( s2 == "light" ) return Difficulty_Easy; - else if( s2 == "medium" ) return Difficulty_Medium; - else if( s2 == "another" ) return Difficulty_Medium; - else if( s2 == "trick" ) return Difficulty_Medium; - else if( s2 == "standard" ) return Difficulty_Medium; - else if( s2 == "difficult") return Difficulty_Medium; - else if( s2 == "hard" ) return Difficulty_Hard; - else if( s2 == "ssr" ) return Difficulty_Hard; - else if( s2 == "maniac" ) return Difficulty_Hard; - else if( s2 == "heavy" ) return Difficulty_Hard; - else if( s2 == "smaniac" ) return Difficulty_Challenge; - else if( s2 == "challenge" ) return Difficulty_Challenge; - else if( s2 == "expert" ) return Difficulty_Challenge; - else if( s2 == "oni" ) return Difficulty_Challenge; - else if( s2 == "edit" ) return Difficulty_Edit; - else return Difficulty_Invalid; -} - const RString &CourseDifficultyToLocalizedString( CourseDifficulty x ) { static auto_ptr g_CourseDifficultyName[NUM_Difficulty]; diff --git a/src/Difficulty.h b/src/Difficulty.h index 48b97a6006..3c7896efd3 100644 --- a/src/Difficulty.h +++ b/src/Difficulty.h @@ -22,8 +22,6 @@ const RString& DifficultyToString( Difficulty dc ); Difficulty StringToDifficulty( const RString& sDC ); LuaDeclareType( Difficulty ); -Difficulty DwiCompatibleStringToDifficulty( const RString& sDC ); - typedef Difficulty CourseDifficulty; const int NUM_CourseDifficulty = NUM_Difficulty; /** @brief Loop through the shown course difficulties. */ diff --git a/src/NotesLoaderDWI.cpp b/src/NotesLoaderDWI.cpp index a822f50259..3bc992d1c5 100644 --- a/src/NotesLoaderDWI.cpp +++ b/src/NotesLoaderDWI.cpp @@ -10,6 +10,7 @@ #include "GameInput.h" #include "NotesLoader.h" #include "PrefsManager.h" +#include "Difficulty.h" #include @@ -140,6 +141,33 @@ static bool Is192( const RString &sStepData, size_t pos ) /** @brief All DWI files use 4 beats per measure. */ const int BEATS_PER_MEASURE = 4; +/* We prefer the normal names; recognize a number of others, too. (They'll get + * normalized when written to SMs, etc.) */ +Difficulty DwiCompatibleStringToDifficulty( const RString& sDC ) +{ + RString s2 = sDC; + s2.MakeLower(); + if( s2 == "beginner" ) return Difficulty_Beginner; + else if( s2 == "easy" ) return Difficulty_Easy; + else if( s2 == "basic" ) return Difficulty_Easy; + else if( s2 == "light" ) return Difficulty_Easy; + else if( s2 == "medium" ) return Difficulty_Medium; + else if( s2 == "another" ) return Difficulty_Medium; + else if( s2 == "trick" ) return Difficulty_Medium; + else if( s2 == "standard" ) return Difficulty_Medium; + else if( s2 == "difficult") return Difficulty_Medium; + else if( s2 == "hard" ) return Difficulty_Hard; + else if( s2 == "ssr" ) return Difficulty_Hard; + else if( s2 == "maniac" ) return Difficulty_Hard; + else if( s2 == "heavy" ) return Difficulty_Hard; + else if( s2 == "smaniac" ) return Difficulty_Challenge; + else if( s2 == "challenge" ) return Difficulty_Challenge; + else if( s2 == "expert" ) return Difficulty_Challenge; + else if( s2 == "oni" ) return Difficulty_Challenge; + else if( s2 == "edit" ) return Difficulty_Edit; + else return Difficulty_Invalid; +} + /** * @brief Look through the notes tag to extract the data. * @param sMode the steps type. diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index b8099a1e01..0369f60a0e 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -45,7 +45,7 @@ void SMLoader::LoadFromSMTokens( out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType ); out.SetDescription( sDescription ); out.SetCredit( sDescription ); // this is often used for both. - out.SetDifficulty( DwiCompatibleStringToDifficulty(sDifficulty) ); + out.SetDifficulty( StringToDifficulty(sDifficulty) ); // Handle hacks that originated back when StepMania didn't have // Difficulty_Challenge. (At least v1.64, possibly v3.0 final...) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index dbb0089494..089e0705bb 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -42,7 +42,7 @@ void SMALoader::LoadFromSMATokens( out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType ); out.SetDescription( sDescription ); out.SetCredit( sDescription ); // this is often used for both. - out.SetDifficulty( DwiCompatibleStringToDifficulty(sDifficulty) ); + out.SetDifficulty( StringToDifficulty(sDifficulty) ); sDescription.MakeLower(); diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 4e511c844a..217b31507a 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -709,7 +709,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="DIFFICULTY" ) { - pNewNotes->SetDifficulty( DwiCompatibleStringToDifficulty( sParams[1] ) ); + pNewNotes->SetDifficulty( StringToDifficulty( sParams[1] ) ); } else if( sValueName=="METER" ) @@ -980,7 +980,7 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat else if( sValueName=="DIFFICULTY" ) { - pNewNotes->SetDifficulty( DwiCompatibleStringToDifficulty( sParams[1] ) ); + pNewNotes->SetDifficulty( StringToDifficulty( sParams[1] ) ); bSSCFormat = true; } From 015fceea7094a52cf2aeee06eb53ecd15102a789 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 03:33:19 -0500 Subject: [PATCH 199/333] small changes --- src/ScreenEvaluation.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ScreenEvaluation.cpp b/src/ScreenEvaluation.cpp index de756c34fc..1f87fe4b97 100644 --- a/src/ScreenEvaluation.cpp +++ b/src/ScreenEvaluation.cpp @@ -357,7 +357,7 @@ void ScreenEvaluation::Init() SET_XY( m_sprPercentFrame[p] ); this->AddChild( m_sprPercentFrame[p] ); - /* Use "ScreenEvaluation Percent" for the [metric set], but position and + /* Use "ScreenEvaluation Percent" in the [metrics], but position and * tween it with "PercentP1X", etc. */ m_Percent[p].SetName( ssprintf("PercentP%d",p+1) ); m_Percent[p].Load( GAMESTATE->m_pPlayerState[p], &m_pStageStats->m_player[p], "ScreenEvaluation Percent", true ); @@ -404,7 +404,8 @@ void ScreenEvaluation::Init() ActorUtil::LoadAllCommands( m_sprActualBar[p][r], m_sName ); SET_XY( m_sprActualBar[p][r] ); - // .99999 is fairly close to 1.00, so we use that + // .99999 is fairly close to 1.00, so we use that. + // todo: allow extra commands for AAA/AAAA? -aj if( m_pStageStats->m_player[p].m_radarActual[r] > 0.99999f ) m_sprActualBar[p][r].RunCommands( BAR_ACTUAL_MAX_COMMAND ); this->AddChild( &m_sprActualBar[p][r] ); @@ -546,12 +547,12 @@ void ScreenEvaluation::Init() SET_XY( m_textDetailText[l][p] ); this->AddChild( &m_textDetailText[l][p] ); - static const int indeces[NUM_DetailLine] = + static const int indices[NUM_DetailLine] = { RadarCategory_TapsAndHolds, RadarCategory_Jumps, RadarCategory_Holds, RadarCategory_Mines, RadarCategory_Hands, RadarCategory_Rolls, RadarCategory_Lifts, RadarCategory_Fakes }; - const int ind = indeces[l]; + const int ind = indices[l]; const int iActual = lrintf(m_pStageStats->m_player[p].m_radarActual[ind]); const int iPossible = lrintf(m_pStageStats->m_player[p].m_radarPossible[ind]); From 84f2457aa487db86cd450e40a23580929f5f74d6 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 07:53:06 -0500 Subject: [PATCH 200/333] [splittiming] Add PlayerState.GetSongPosition() and GameState.GetSongPosition() to Lua; add lua bindings to SongPosition --- src/GameState.cpp | 3 +++ src/PlayerState.cpp | 1 + src/SongPosition.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/GameState.cpp b/src/GameState.cpp index 8205d4143f..7b1be3f3c9 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2251,11 +2251,13 @@ public: DEFINE_METHOD( GetHardestStepsDifficulty, GetHardestStepsDifficulty() ) DEFINE_METHOD( IsEventMode, IsEventMode() ) DEFINE_METHOD( GetNumPlayersEnabled, GetNumPlayersEnabled() ) + //TODO: move GetSongBeat (etc.) to a compatbility layer DEFINE_METHOD( GetSongBeat, m_Position.m_fSongBeat ) DEFINE_METHOD( GetSongBeatVisible, m_Position.m_fSongBeatVisible ) DEFINE_METHOD( GetSongBPS, m_Position.m_fCurBPS ) DEFINE_METHOD( GetSongFreeze, m_Position.m_bFreeze ) DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay ) + DEFINE_METHOD( GetSongPosition, m_Position ) DEFINE_METHOD( GetGameplayLeadIn, m_bGameplayLeadIn ) DEFINE_METHOD( GetCoins, m_iCoins ) DEFINE_METHOD( IsSideJoined, m_bSideIsJoined[Enum::Check(L, 1)] ) @@ -2465,6 +2467,7 @@ public: ADD_METHOD( GetSongBPS ); ADD_METHOD( GetSongFreeze ); ADD_METHOD( GetSongDelay ); + ADD_METHOD( GetSongPosition ); ADD_METHOD( GetGameplayLeadIn ); ADD_METHOD( GetCoins ); ADD_METHOD( IsSideJoined ); diff --git a/src/PlayerState.cpp b/src/PlayerState.cpp index d6583059bf..ac76b0fbc2 100644 --- a/src/PlayerState.cpp +++ b/src/PlayerState.cpp @@ -197,6 +197,7 @@ class LunaPlayerState: public Luna { public: DEFINE_METHOD( GetPlayerNumber, m_PlayerNumber ); + DEFINE_METHOD( GetSongPosition, m_Position ); DEFINE_METHOD( GetMultiPlayerNumber, m_mp ); DEFINE_METHOD( GetPlayerController, m_PlayerController ); static int SetPlayerOptions( T* p, lua_State *L ) diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index bcfee26f80..134c3f8b5d 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -74,6 +74,38 @@ void SongPosition::Reset() } +//lua start +#include "LuaBinding.h" +class LunaSongPosition: public Luna +{ +public: + DEFINE_METHOD( GetMusicSecondsVisible, m_fMusicSecondsVisible ); + DEFINE_METHOD( GetSongBeatVisible, m_fSongBeatVisible ); + DEFINE_METHOD( GetMusicSeconds, m_fMusicSeconds ); + DEFINE_METHOD( GetSongBeat, m_fSongBeat ); + DEFINE_METHOD( GetSongBeatNoOffset, m_fSongBeatNoOffset ); + DEFINE_METHOD( GetCurBPS, m_fCurBPS ); + DEFINE_METHOD( GetFreeze, m_bFreeze ); + DEFINE_METHOD( GetDelay, m_bDelay ); + DEFINE_METHOD( GetWarpBeginRow, m_fWarpBeginRow ); + DEFINE_METHOD( GetWarpDestination, m_fWarpDestination ); + + LunaSongPosition() + { + ADD_METHOD( GetMusicSecondsVisible ); + ADD_METHOD( GetSongBeatVisible ); + ADD_METHOD( GetMusicSeconds ); + ADD_METHOD( GetSongBeat ); + ADD_METHOD( GetSongBeatNoOffset ); + ADD_METHOD( GetCurBPS ); + ADD_METHOD( GetFreeze ); + ADD_METHOD( GetDelay ); + ADD_METHOD( GetWarpBeginRow ); + ADD_METHOD( GetWarpDestination ); + } +}; + +LUA_REGISTER_CLASS( SongPosition ) /** * @file * @author Thai Pangsakulyanont (c) 2011 From 4d14654147061e0f075ee68addbf3ce6f539aa79 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 08:17:32 -0500 Subject: [PATCH 201/333] [splittiming] remove GameState "current timing" functions; add compatibility functions to 01 compat.lua --- Themes/_fallback/Scripts/01 alias.lua | 2 +- Themes/_fallback/Scripts/01 compat.lua | 12 +++++++++++- src/GameState.cpp | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/Scripts/01 alias.lua b/Themes/_fallback/Scripts/01 alias.lua index 05935425bf..126d9c69ef 100644 --- a/Themes/_fallback/Scripts/01 alias.lua +++ b/Themes/_fallback/Scripts/01 alias.lua @@ -20,4 +20,4 @@ local _screen = { h = SCREEN_HEIGHT, cx = SCREEN_CENTER_X, cy = SCREEN_CENTER_Y -} \ No newline at end of file +} diff --git a/Themes/_fallback/Scripts/01 compat.lua b/Themes/_fallback/Scripts/01 compat.lua index c2f171e1f0..dbdf4a819c 100644 --- a/Themes/_fallback/Scripts/01 compat.lua +++ b/Themes/_fallback/Scripts/01 compat.lua @@ -63,4 +63,14 @@ end if ScreenMetric then ScreenMetric = Screen.Metric -end \ No newline at end of file +end + +--[[ GameState ]] +--Aliases for old GAMESTATE timing functions. +--These have been converted to SongPosition, but most themes still use these old functions. + +function GameState:GetSongBeat() return self:GetSongPosition():GetSongBeat() end +function GameState:GetSongBeatNoOffset() return self:GetSongPosition():GetSongBeatNoOffset() end +function GameState:GetSongBPS() return self:GetSongPosition():GetCurBPS() end +function GameState:GetSongDelay() return self:GetSongPosition:GetDelay() end +function GameState:GetSongFreeze() return self:GetSongPosition:GetFreeze() end diff --git a/src/GameState.cpp b/src/GameState.cpp index 7b1be3f3c9..f9451ff119 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2462,11 +2462,11 @@ public: ADD_METHOD( GetHardestStepsDifficulty ); ADD_METHOD( IsEventMode ); ADD_METHOD( GetNumPlayersEnabled ); - ADD_METHOD( GetSongBeat ); + /*ADD_METHOD( GetSongBeat ); ADD_METHOD( GetSongBeatVisible ); ADD_METHOD( GetSongBPS ); ADD_METHOD( GetSongFreeze ); - ADD_METHOD( GetSongDelay ); + ADD_METHOD( GetSongDelay );*/ ADD_METHOD( GetSongPosition ); ADD_METHOD( GetGameplayLeadIn ); ADD_METHOD( GetCoins ); From ec09a40d39c6517b170ec0cba525d4d5c9c9182d Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 08:21:16 -0500 Subject: [PATCH 202/333] [splittiming] finish removing bindings --- src/GameState.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index f9451ff119..9ed0c33f78 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2251,12 +2251,11 @@ public: DEFINE_METHOD( GetHardestStepsDifficulty, GetHardestStepsDifficulty() ) DEFINE_METHOD( IsEventMode, IsEventMode() ) DEFINE_METHOD( GetNumPlayersEnabled, GetNumPlayersEnabled() ) - //TODO: move GetSongBeat (etc.) to a compatbility layer - DEFINE_METHOD( GetSongBeat, m_Position.m_fSongBeat ) + /*DEFINE_METHOD( GetSongBeat, m_Position.m_fSongBeat ) DEFINE_METHOD( GetSongBeatVisible, m_Position.m_fSongBeatVisible ) DEFINE_METHOD( GetSongBPS, m_Position.m_fCurBPS ) DEFINE_METHOD( GetSongFreeze, m_Position.m_bFreeze ) - DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay ) + DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay )*/ DEFINE_METHOD( GetSongPosition, m_Position ) DEFINE_METHOD( GetGameplayLeadIn, m_bGameplayLeadIn ) DEFINE_METHOD( GetCoins, m_iCoins ) From 2f83c163276b5e601d31ad125ff99a4983d61910 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 13:06:46 -0400 Subject: [PATCH 203/333] [splittiming] Minor typo. --- src/SongPosition.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 134c3f8b5d..5aa148e552 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -87,7 +87,7 @@ public: DEFINE_METHOD( GetCurBPS, m_fCurBPS ); DEFINE_METHOD( GetFreeze, m_bFreeze ); DEFINE_METHOD( GetDelay, m_bDelay ); - DEFINE_METHOD( GetWarpBeginRow, m_fWarpBeginRow ); + DEFINE_METHOD( GetWarpBeginRow, m_iWarpBeginRow ); DEFINE_METHOD( GetWarpDestination, m_fWarpDestination ); LunaSongPosition() @@ -105,7 +105,7 @@ public: } }; -LUA_REGISTER_CLASS( SongPosition ) +LUA_REGISTER_CLASS( SongPosition ); /** * @file * @author Thai Pangsakulyanont (c) 2011 From 702ebfe94b1f3ec836ab6e678f3f96710971384c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 13:09:13 -0400 Subject: [PATCH 204/333] [splittiming] The start of SpeedSegments. ...I'm seriously debating moving the structs to their own file at this rate. It's getting a tiny bit unwieldy. --- src/TimingData.h | 107 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/TimingData.h b/src/TimingData.h index 2c5ad2ecf6..c1d1b2ea87 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -647,6 +647,107 @@ struct LabelSegment bool operator>=( const LabelSegment &other ) const { return !operator<(other); } }; +/** + * @brief Identifies when the arrow scroll changes. + * + * SpeedSegments take a Player's scrolling BPM (Step's BPM * speed mod), + * and then multiplies it with the percentage value. No matter the player's + * speed mod, the ratio will be the same. Unlike forced attacks, these + * cannot be turned off at a set time: reset it by setting the precentage + * back to 1. + * + * These were inspired by the Pump It Up series. */ +struct SpeedSegment +{ + /** @brief Sets up the SpeedSegment with default values. */ + SpeedSegment(): m_iStartRow(0), m_fPercent(1), m_fWait(0) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param i The row this activates. + * @param p The percentage to use. */ + SpeedSegment(int i, float p): m_iStartRow(0), m_fPercent(p), m_fWait(0) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param r The beat this activates. + * @param p The percentage to use. */ + SpeedSegment(float r, float p): m_iStartRow(BeatToNoteRow(r)), + m_fPercent(p), m_fWait(0) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param i The row this activates. + * @param p The percentage to use. + * @param w The number of beats to wait. */ + SpeedSegment(int i, float p, float w): m_iStartRow(i), + m_fPercent(p), m_fWait(w) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param r The beat this activates. + * @param p The percentage to use. + * @param w The number of beats to wait. */ + SpeedSegment(float r, float p, float w): m_iStartRow(BeatToNoteRow(r)), + m_fPercent(p), m_fWait(w) {} + + /** @brief The row in which the ComboSegment activates. */ + int m_iStartRow; + /** @brief The percentage to use when multiplying the Player's BPM. */ + float m_fPercent; + /** + * @brief The number of beats to wait for the change to take place. + * + * A value of 0 means this is immediate. */ + float m_fWait; + + /** + * @brief Compares two SpeedSegments to see if they are equal to each other. + * @param other the other SpeedSegment to compare to. + * @return the equality of the two segments. + */ + bool operator==( const SpeedSegment &other ) const + { + COMPARE( m_iStartRow ); + COMPARE( m_fPercent ); + COMPARE( m_fWait ); + return true; + } + /** + * @brief Compares two SpeedSegments to see if they are not equal to each other. + * @param other the other SpeedSegment to compare to. + * @return the inequality of the two segments. + */ + bool operator!=( const SpeedSegment &other ) const { return !operator==(other); } + /** + * @brief Compares two SpeedSegments to see if one is less than the other. + * @param other the other SpeedSegment to compare to. + * @return the truth/falsehood of if the first is less than the second. + */ + bool operator<( const SpeedSegment &other ) const { return m_iStartRow < other.m_iStartRow; } + /** + * @brief Compares two SpeedSegments to see if one is less than or equal to the other. + * @param other the other SpeedSegment to compare to. + * @return the truth/falsehood of if the first is less or equal to than the second. + */ + bool operator<=( const SpeedSegment &other ) const + { + return ( operator<(other) || operator==(other) ); + } + /** + * @brief Compares two SpeedSegments to see if one is greater than the other. + * @param other the other SpeedSegment to compare to. + * @return the truth/falsehood of if the first is greater than the second. + */ + bool operator>( const SpeedSegment &other ) const { return !operator<=(other); } + /** + * @brief Compares two SpeedSegments to see if one is greater than or equal to the other. + * @param other the other SpeedSegment to compare to. + * @return the truth/falsehood of if the first is greater than or equal to the second. + */ + bool operator>=( const SpeedSegment &other ) const { return !operator<(other); } +}; + /** * @brief Holds data for translating beats<->seconds. @@ -1305,8 +1406,12 @@ public: COMPARE( m_ComboSegments.size() ); for( unsigned i=0; i m_LabelSegments; + /** @brief The collection of SpeedSegments. */ + vector m_SpeedSegments; /** * @brief The initial offset of a song. */ From 9870ed9ebb19e036f9f2126ff691860330d877c7 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 12:16:02 -0500 Subject: [PATCH 205/333] [splittiming] another fix for le bad lua bindings --- src/SongPosition.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SongPosition.h b/src/SongPosition.h index 9ca7bbe778..830924b84a 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -6,6 +6,8 @@ #include "LightsManager.h" #include "MessageManager.h" #include "TimingData.h" +//XXX: where does this come from? might need another include +struct lua_State; class SongPosition { @@ -36,6 +38,8 @@ class SongPosition void Reset(); void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); + // Lua + void PushSelf( lua_State *L ); }; #endif From 9ffe6166e2927df4065584d1141003079892ae57 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 13:48:10 -0400 Subject: [PATCH 206/333] [splittiming] Implement, add lua hook. --- Docs/Luadoc/Lua.xml | 1 + Docs/Luadoc/LuaDocumentation.xml | 3 + src/TimingData.cpp | 124 ++++++++++++++++++++++++++++++- src/TimingData.h | 99 ++++++++++++++++++++++++ 4 files changed, 226 insertions(+), 1 deletion(-) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index f41bb848cb..966502afbc 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1405,6 +1405,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 39df9f4188..24492431aa 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -3516,6 +3516,9 @@ Returns true if the TimingData contains warps. + + Returns true if the TimingData contains speed scrolling changes. + diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 2f93424bc7..45302128b8 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -68,6 +68,11 @@ void TimingData::AddLabelSegment( const LabelSegment &seg ) m_LabelSegments.insert( upper_bound(m_LabelSegments.begin(), m_LabelSegments.end(), seg), seg ); } +void TimingData::AddSpeedSegment( const SpeedSegment &seg ) +{ + m_SpeedSegments.insert( upper_bound(m_SpeedSegments.begin(), m_SpeedSegments.end(), seg), seg ); +} + /* Change an existing BPM segment, merge identical segments together or insert a new one. */ void TimingData::SetBPMAtRow( int iNoteRow, float fBPM ) { @@ -250,6 +255,47 @@ void TimingData::SetLabelAtRow( int iRow, const RString sLabel ) } } +void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait ) +{ + unsigned i; + for( i = 0; i < m_SpeedSegments.size(); i++ ) + { + if( m_SpeedSegments[i].m_iStartRow >= iRow) + break; + } + + if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].m_iStartRow != iRow ) + { + if( i == 0 || + ( m_SpeedSegments[i-1].m_fPercent != fPercent + || m_SpeedSegments[i-1].m_fWait != fWait ) ) + AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait) ); + } + else + { + if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent + && m_SpeedSegments[i-1].m_fWait == fWait ) + m_SpeedSegments.erase( m_SpeedSegments.begin()+i, + m_SpeedSegments.begin()+i+1 ); + else + { + m_SpeedSegments[i].m_fPercent = fPercent; + m_SpeedSegments[i].m_fWait = fWait; + } + } +} + +void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent ) +{ + SetSpeedAtRow( iRow, fPercent, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait ); +} + +void TimingData::SetSpeedWaitAtRow( int iRow, float fWait ) +{ + SetSpeedAtRow( iRow, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, fWait ); +} + + float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const { for( unsigned i=0; i(i); } +int TimingData::GetSpeedSegmentIndexAtRow( int iRow ) const +{ + unsigned i; + for (i=0; i < m_SpeedSegments.size() - 1; i++ ) + if( m_SpeedSegments[i+1].m_iStartRow > iRow ) + break; + return static_cast(i); +} + BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) { static BPMSegment empty; @@ -451,6 +516,15 @@ TimeSignatureSegment& TimingData::GetTimeSignatureSegmentAtRow( int iRow ) return m_vTimeSignatureSegments[i]; } +SpeedSegment& TimingData::GetSpeedSegmentAtRow( int iRow ) +{ + unsigned i; + for( i=0; i iRow ) + break; + return m_SpeedSegments[i]; +} + int TimingData::GetTimeSignatureNumeratorAtRow( int iRow ) { return GetTimeSignatureSegmentAtRow( iRow ).m_iNumerator; @@ -845,6 +919,17 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool m_LabelSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; } + for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + const int iSegStart = m_SpeedSegments[i].m_iStartRow; + if( iSegStart < iStartIndex ) + continue; + else if( iSegStart > iEndIndex ) + m_SpeedSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + else + m_SpeedSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + } + // adjust BPM changes to preserve timing if( bAdjustBPM ) { @@ -929,6 +1014,14 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) continue; labl.m_iStartRow += iRowsToAdd; } + + for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + SpeedSegment &sped = m_SpeedSegments[i]; + if( sped.m_iStartRow < iStartRow ) + continue; + sped.m_iStartRow += iRowsToAdd; + } if( iStartRow == 0 ) { @@ -1086,6 +1179,22 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } labl.m_iStartRow -= iRowsToDelete; } + + for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + SpeedSegment &sped = m_SpeedSegments[i]; + + if( sped.m_iStartRow < iStartRow ) + continue; + + if( sped.m_iStartRow < iStartRow+iRowsToDelete ) + { + m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); + --i; + continue; + } + sped.m_iStartRow -= iRowsToDelete; + } this->SetBPMAtRow( iStartRow, fNewBPM ); } @@ -1133,7 +1242,13 @@ void TimingData::TidyUpData() LabelSegment seg(0, "Song Start"); m_LabelSegments.push_back( seg ); } - + + // Always be sure there is a starting speed. + if( m_SpeedSegments.empty() ) + { + SpeedSegment seg(0, 1, 0); + m_SpeedSegments.push_back( seg ); + } } @@ -1155,6 +1270,11 @@ bool TimingData::HasWarps() const return m_WarpSegments.size()>0; } +bool TimingData::HasSpeedChanges() const +{ + return m_SpeedSegments.size()>1; +} + void TimingData::NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const { iMeasureIndexOut = 0; @@ -1201,6 +1321,7 @@ public: static int HasStops( T* p, lua_State *L ) { lua_pushboolean(L, p->HasStops()); return 1; } static int HasBPMChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasBpmChanges()); return 1; } static int HasWarps( T* p, lua_State *L ) { lua_pushboolean(L, p->HasWarps()); return 1; } + static int HasSpeedChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasSpeedChanges()); return 1; } static int GetStops( T* p, lua_State *L ) { vector vStops; @@ -1288,6 +1409,7 @@ public: ADD_METHOD( HasStops ); ADD_METHOD( HasBPMChanges ); ADD_METHOD( HasWarps ); + ADD_METHOD( HasSpeedChanges ); ADD_METHOD( GetStops ); ADD_METHOD( GetDelays ); ADD_METHOD( GetBPMs ); diff --git a/src/TimingData.h b/src/TimingData.h index c1d1b2ea87..d68e2ec98e 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1339,6 +1339,101 @@ public: */ float GetNextLabelSegmentBeatAtBeat( float fBeat ) const { return GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); } + + /** + * @brief Retrieve the Speed's percent at the given row. + * @param iNoteRow the row in question. + * @return the percent. + */ + float GetSpeedPercentAtRow( int iNoteRow ); + /** + * @brief Retrieve the Speed's percent at the given beat. + * @param fBeat the beat in question. + * @return the percent. + */ + float GetSpeedPercentAtBeat( float fBeat ) { return GetSpeedPercentAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the Speed's wait at the given row. + * @param iNoteRow the row in question. + * @return the wait. + */ + float GetSpeedWaitAtRow( int iNoteRow ); + /** + * @brief Retrieve the Speed's wait at the given beat. + * @param fBeat the beat in question. + * @return the wait. + */ + float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Set the row to have the new Speed. + * @param iNoteRow the row to have the new Speed. + * @param fPercent the percent. + * @param fWait the wait. + */ + void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait ); + /** + * @brief Set the beat to have the new Speed. + * @param fBeat the beat to have the new Speed. + * @param fPercent the percent. + * @param fWait the wait. + */ + void SetSpeedAtBeat( float fBeat, float fPercent, float fWait ) { SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait ); } + /** + * @brief Set the row to have the new Speed percent. + * @param iNoteRow the row to have the new Speed percent. + * @param fPercent the percent. + */ + void SetSpeedPercentAtRow( int iNoteRow, float fPercent ); + /** + * @brief Set the beat to have the new Speed percent. + * @param fBeat the beat to have the new Speed percent. + * @param fPercent the percent. + */ + void SetSpeedPercentAtBeat( float fBeat, float fPercent ) { SetSpeedPercentAtRow( BeatToNoteRow(fBeat), fPercent); } + /** + * @brief Set the row to have the new Speed wait. + * @param iNoteRow the row to have the new Speed wait. + * @param fWait the wait. + */ + void SetSpeedWaitAtRow( int iNoteRow, float fWait ); + /** + * @brief Set the beat to have the new Speed wait. + * @param fBeat the beat to have the new Speed wait. + * @param fWait the wait. + */ + void SetSpeedWaitAtBeat( float fBeat, float fWait ) { SetSpeedWaitAtRow( BeatToNoteRow(fBeat), fWait); } + /** + * @brief Retrieve the SpeedSegment at the specified row. + * @param iNoteRow the row that has a SpeedSegment. + * @return the SpeedSegment in question. + */ + SpeedSegment& GetSpeedSegmentAtRow( int iNoteRow ); + /** + * @brief Retrieve the SpeedSegment at the specified beat. + * @param fBeat the beat that has a SpeedSegment. + * @return the SpeedSegment in question. + */ + SpeedSegment& GetSpeedSegmentAtBeat( float fBeat ) { return GetSpeedSegmentAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the index of the SpeedSegments at the specified row. + * @param iNoteRow the row that has a SpeedSegment. + * @return the SpeedSegment's index in question. + */ + int GetSpeedSegmentIndexAtRow( int iNoteRow ) const; + /** + * @brief Retrieve the index of the SpeedSegments at the specified beat. + * @param fBeat the beat that has a SpeedSegment. + * @return the SpeedSegment's index in question. + */ + int GetSpeedSegmentIndexAtBeat( float fBeat ) const { return GetSpeedSegmentIndexAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Add the SpeedSegment to the TimingData. + * @param seg the new SpeedSegment. + */ + void AddSpeedSegment( const SpeedSegment &seg ); + + + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; @@ -1381,6 +1476,10 @@ public: * @return true if there is at least one warp, false otherwise. */ bool HasWarps() const; + /** + * @brief View the TimingData to see if a song changes its speed scrolling at any point. + * @return true if there is at least one change, false otherwise. */ + bool HasSpeedChanges() const; /** * @brief Compare two sets of timing data to see if they are equal. * @param other the other TimingData. From 640f8fe9fc3c9133c18db2afc67065877f93d3e2 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 14:05:02 -0400 Subject: [PATCH 207/333] [splittiming] PlayerOptions -> HasTimingChanges. Steps gained most of the functionality and lua doc. Leaving song version in: may still have a use thanks to #DISPLAYBPM. --- Docs/Luadoc/Lua.xml | 1 + Docs/Luadoc/LuaDocumentation.xml | 3 +++ src/PlayerOptions.cpp | 2 +- src/Steps.cpp | 18 ++++++++++++++++++ src/Steps.h | 5 +++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 966502afbc..dfb4c7cce3 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1349,6 +1349,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 24492431aa..df9f17081b 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -3368,6 +3368,9 @@ Returns the numerical difficulty of the Steps. + + Returns true if the song has significant timing changes. + Returns the complete list of RadarValues for player pn. Use to grab a specific value. diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 036f1d314c..cbfb031bbf 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -680,7 +680,7 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps, PlayerNumber pn ) const { - if( m_fTimeSpacing && pSong->HasSignificantBpmChangesOrStops() ) + if( m_fTimeSpacing && pSteps->HasSignificantTimingChanges() ) return true; const RadarValues &rv = pSteps->GetRadarValues( pn ); if( m_bTransforms[TRANSFORM_NOHOLDS] && rv[RadarCategory_Holds]>0 ) diff --git a/src/Steps.cpp b/src/Steps.cpp index 5c2c91f063..3174e011b2 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -402,6 +402,21 @@ void Steps::SetMeter( int meter ) m_iMeter = meter; } +bool Steps::HasSignificantTimingChanges() const +{ + if( m_Timing.HasStops() ) + return true; + + /* TODO: Deal with DisplayBPM here...if possible? + * Song's version may still be useful. */ + + else if( m_Timing.HasBpmChanges() || m_Timing.HasWarps() || m_Timing.HasSpeedChanges() ) + { + return true; + } + return false; +} + void Steps::SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] ) { DeAutogen(); @@ -426,6 +441,8 @@ public: DEFINE_METHOD( IsAnEdit, IsAnEdit() ) DEFINE_METHOD( IsAPlayerEdit, IsAPlayerEdit() ) + static int HasSignificantTimingChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasSignificantTimingChanges()); return 1; } + static int GetRadarValues( T* p, lua_State *L ) { PlayerNumber pn = Enum::Check(L, 1); @@ -454,6 +471,7 @@ public: ADD_METHOD( GetFilename ); ADD_METHOD( GetHash ); ADD_METHOD( GetMeter ); + ADD_METHOD( HasSignificantTimingChanges ); ADD_METHOD( GetRadarValues ); //ADD_METHOD( GetSMNoteData ); ADD_METHOD( GetStepsType ); diff --git a/src/Steps.h b/src/Steps.h index e796f99847..078295bc71 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -120,6 +120,11 @@ public: /** @brief Timing data */ TimingData m_Timing; + + /** + * @brief Determine if the Steps have any major timing changes during gameplay. + * @return true if it does, or false otherwise. */ + bool HasSignificantTimingChanges() const; // Lua void PushSelf( lua_State *L ); From 6975b9393a79d1a7f03c0964e44efc0bbd58a8bd Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 13:34:01 -0500 Subject: [PATCH 208/333] [splittiming] GetSongPosition works. --- src/GameState.cpp | 6 +++++- src/PlayerState.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 9ed0c33f78..3b4f792986 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2256,7 +2256,11 @@ public: DEFINE_METHOD( GetSongBPS, m_Position.m_fCurBPS ) DEFINE_METHOD( GetSongFreeze, m_Position.m_bFreeze ) DEFINE_METHOD( GetSongDelay, m_Position.m_bDelay )*/ - DEFINE_METHOD( GetSongPosition, m_Position ) + static int GetSongPosition( T* p, lua_State *L ) + { + p->m_Position.PushSelf(L); + return 1; + } DEFINE_METHOD( GetGameplayLeadIn, m_bGameplayLeadIn ) DEFINE_METHOD( GetCoins, m_iCoins ) DEFINE_METHOD( IsSideJoined, m_bSideIsJoined[Enum::Check(L, 1)] ) diff --git a/src/PlayerState.cpp b/src/PlayerState.cpp index ac76b0fbc2..9d7b652851 100644 --- a/src/PlayerState.cpp +++ b/src/PlayerState.cpp @@ -197,7 +197,11 @@ class LunaPlayerState: public Luna { public: DEFINE_METHOD( GetPlayerNumber, m_PlayerNumber ); - DEFINE_METHOD( GetSongPosition, m_Position ); + static int GetSongPosition( T* p, lua_State *L ) + { + p->m_Position.PushSelf(L); + return 1; + } DEFINE_METHOD( GetMultiPlayerNumber, m_mp ); DEFINE_METHOD( GetPlayerController, m_PlayerController ); static int SetPlayerOptions( T* p, lua_State *L ) @@ -247,6 +251,7 @@ public: ADD_METHOD( GetPlayerOptionsArray ); ADD_METHOD( GetPlayerOptionsString ); ADD_METHOD( GetCurrentPlayerOptions ); + ADD_METHOD( GetSongPosition ); ADD_METHOD( GetHealthState ); } }; From f8f4453637d4ae7a959f55e7f8c27087bed29680 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 13:38:41 -0500 Subject: [PATCH 209/333] [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and replace them with DebugStartOnCommand, DebugBackOnCommand, and DebugTweenOffCommand. --- Docs/Changelog_sm5.txt | 6 ++++++ Themes/_fallback/metrics.ini | 3 +++ src/ScreenGameplay.cpp | 17 +++-------------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index daf91cd16f..91fb2ccaf9 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,12 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/15 +---------- +* [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and + replace them with DebugStartOnCommand, DebugBackOnCommand, and + DebugTweenOffCommand. [AJ] + 2011/05/14 ---------- * [ModIcon] Added StopWords metric. [AJ] diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 1b23a2200c..b80fa71588 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3211,6 +3211,9 @@ SongOptionsOffCommand= DebugX=SCREEN_CENTER_X DebugY=SCREEN_BOTTOM-72 DebugOnCommand=zoom,0.75 +DebugStartOnCommand=stoptweening;diffusealpha,0;linear,1/8;diffusealpha,1 +DebugBackOnCommand=stoptweening;diffusealpha,0;linear,1/8;diffusealpha,1 +DebugTweenOffCommand=stoptweening;linear,1/8;diffusealpha,0 # SongNumberFormat="%d" SongNumberP1X=THEME:GetMetric(Var "LoadingScreen","PlayerP1OnePlayerOneSideX") - 60 diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 5ffaa849db..b3dbc5a791 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -2156,11 +2156,7 @@ void ScreenGameplay::Input( const InputEventPlus &input ) else if( input.type==IET_FIRST_PRESS && m_GiveUpTimer.IsZero() ) { m_textDebug.SetText( GIVE_UP_START_TEXT ); - // todo: un-hardcode commands and move to metrics -aj - m_textDebug.StopTweening(); - m_textDebug.SetDiffuse( RageColor(1,1,1,0) ); - m_textDebug.BeginTweening( 1/8.f ); - m_textDebug.SetDiffuse( RageColor(1,1,1,1) ); + m_textDebug.PlayCommand( "StartOn" ); m_GiveUpTimer.Touch(); // start the timer } @@ -2187,18 +2183,11 @@ void ScreenGameplay::Input( const InputEventPlus &input ) else if( PREFSMAN->m_bDelayedBack && input.type==IET_FIRST_PRESS ) { m_textDebug.SetText( GIVE_UP_BACK_TEXT ); - // todo: un-hardcode commands and move to metrics -aj - m_textDebug.StopTweening(); - m_textDebug.SetDiffuse( RageColor(1,1,1,0) ); - m_textDebug.BeginTweening( 1/8.f ); - m_textDebug.SetDiffuse( RageColor(1,1,1,1) ); + m_textDebug.PlayCommand( "BackOn" ); } else if( PREFSMAN->m_bDelayedBack && input.type==IET_RELEASE ) { - // todo: un-hardcode commands and move to metrics -aj - m_textDebug.StopTweening(); - m_textDebug.BeginTweening( 1/8.f ); - m_textDebug.SetDiffuse( RageColor(1,1,1,0) ); + m_textDebug.PlayCommand( "TweenOff" ); } return; From 5e3aeb69c9d0d3ce7d9a36db042680a5f23ceeac Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 13:49:05 -0500 Subject: [PATCH 210/333] added stepstype to an assert msg --- src/ScreenHowToPlay.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ScreenHowToPlay.cpp b/src/ScreenHowToPlay.cpp index 7deca6dd40..747a0bf18b 100644 --- a/src/ScreenHowToPlay.cpp +++ b/src/ScreenHowToPlay.cpp @@ -144,8 +144,7 @@ void ScreenHowToPlay::Init() const Style* pStyle = GAMESTATE->GetCurrentStyle(); Steps *pSteps = SongUtil::GetStepsByDescription( &m_Song, pStyle->m_StepsType, "" ); - // todo: make StepsType human readable. -aj - ASSERT_M( pSteps != NULL, "No playable steps for ScreenHowToPlay" ); + ASSERT_M( pSteps != NULL, ssprintf("No playable steps of StepsType '%s' for ScreenHowToPlay", StringConversion::ToString(pStyle->m_StepsType).c_str()) ); NoteData tempNoteData; pSteps->GetNoteData( tempNoteData ); From 13d40682c5f4bff902e2503b6a8eb34e7af584c5 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 14:02:39 -0500 Subject: [PATCH 211/333] small cleanup --- src/OptionsCursor.cpp | 2 +- src/OptionsCursor.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OptionsCursor.cpp b/src/OptionsCursor.cpp index a18ce96750..b1a69a8c14 100644 --- a/src/OptionsCursor.cpp +++ b/src/OptionsCursor.cpp @@ -24,7 +24,7 @@ OptionsCursor::OptionsCursor( const OptionsCursor &cpy ): m_iOriginalCanGoLeftX( cpy.m_iOriginalCanGoLeftX ), m_iOriginalCanGoRightX( cpy.m_iOriginalCanGoRightX ) { - /* Re-add children, or m_SubActors will point to cpy's children and not our own. */ + // Re-add children, or m_SubActors will point to cpy's children and not our own. m_SubActors.clear(); this->AddChild( m_sprMiddle ); this->AddChild( m_sprLeft ); diff --git a/src/OptionsCursor.h b/src/OptionsCursor.h index cf27850d4e..9f0652fe24 100644 --- a/src/OptionsCursor.h +++ b/src/OptionsCursor.h @@ -28,11 +28,11 @@ protected: AutoActor m_sprMiddle; AutoActor m_sprLeft; AutoActor m_sprRight; - + AutoActor m_sprCanGoLeft; AutoActor m_sprCanGoRight; - // save the metrics-set X because it gets oblitterated on a call to SetBarWidth + // save the metrics-set X because it gets obliterated on a call to SetBarWidth int m_iOriginalLeftX; int m_iOriginalRightX; int m_iOriginalCanGoLeftX; From 3b684e8c20a62a922d2904620ec055ed776874d6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 15:24:36 -0400 Subject: [PATCH 212/333] [splittiming] Write out the #SPEEDS tag. We're not incrementing the version due to 0.70 being the main one with Split Timing. If requested, maybe a version 0.64 or something. --- src/NotesLoaderSMA.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/NotesLoaderSMA.h | 1 + src/NotesLoaderSSC.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/NotesLoaderSSC.h | 1 + src/NotesWriterSSC.cpp | 9 +++++++++ 5 files changed, 95 insertions(+) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 16cbeaa1fe..fb7d1fb11d 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -306,6 +306,48 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) } } +void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector vs1; + split( sParam, ",", vs1 ); + + FOREACH_CONST( RString, vs1, s1 ) + { + vector vs2; + split( *s1, "=", vs2 ); + + if( vs2[0] == 0 ) // First one always seems to have 2. + { + vs2.push_back(0); + } + + if( vs2.size() < 3 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with %i values.", (int)vs2.size() ); + continue; + } + + const float fBeat = RowToBeat( vs2[0], iRowsPerBeat ); + + SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] )); + + if( fBeat < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f.", fBeat ); + continue; + } + + if( seg.m_fWait < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, fWait %f.", fBeat, seg.m_fWait ); + continue; + } + + out.AddSpeedSegment( seg ); + } +} + + void SMALoader::LoadFromSMATokens( RString sStepsType, RString sDescription, diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index 1c40b462f2..af397205fb 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -47,6 +47,7 @@ namespace SMALoader void ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam ); float RowToBeat( RString sLine, const int iRowsPerBeat ); }; diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index b576d26ca0..8003a20754 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -126,6 +126,48 @@ void SSCLoader::ProcessCombos( TimingData &out, const RString sParam ) } } +void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) +{ + vector vs1; + split( sParam, ",", vs1 ); + + FOREACH_CONST( RString, vs1, s1 ) + { + vector vs2; + split( *s1, "=", vs2 ); + + if( vs2[0] == 0 ) // First one always seems to have 2. + { + vs2.push_back(0); + } + + if( vs2.size() < 3 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with %i values.", (int)vs2.size() ); + continue; + } + + const float fBeat = StringToFloat( vs2[0] ); + + SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] )); + + if( fBeat < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f.", fBeat ); + continue; + } + + if( seg.m_fWait < 0 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, fWait %f.", fBeat, seg.m_fWait ); + continue; + } + + out.AddSpeedSegment( seg ); + } +} + + bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache ) { LOG->Trace( "Song::LoadFromSSCFile(%s)", sPath.c_str() ); diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index 7d185cc690..c78231677b 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -80,6 +80,7 @@ namespace SSCLoader void ProcessWarps( TimingData &, const RString ); void ProcessLabels( TimingData &, const RString ); void ProcessCombos( TimingData &, const RString ); + void ProcessSpeeds( TimingData &, const RString ); } #endif /** diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3e7882741e..3d036c538c 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -76,6 +76,7 @@ struct TimingTagWriter { void Write( const int row, const float value ) { Write( row, ssprintf( "%.6f", value ) ); } void Write( const int row, const int value ) { Write( row, ssprintf( "%d", value ) ); } void Write( const int row, const int a, const int b ) { Write( row, ssprintf( "%d=%d", a, b ) ); } + void Write( const int row, const float a, const float b ) { Write( row, ssprintf( "%.6f=%.6f", a, b) ); } void Init( const RString sTag ) { m_sNext = "#" + sTag + ":"; } void Finish( ) { m_pvsLines->push_back( ( m_sNext != "," ? m_sNext : "" ) + ";" ); } @@ -131,6 +132,14 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo w.Write( cs->m_iStartRow, cs->m_iCombo ); w.Finish(); + if( !bIsSong ) + { + w.Init( "SPEEDS" ); + FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) + w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait ); + w.Finish(); + } + w.Init( "LABELS" ); FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls ) w.Write( ls->m_iStartRow, ls->m_sLabel.c_str() ); From ad1c4cabce7e318134601976aadfe450665f4a8b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 15:27:02 -0400 Subject: [PATCH 213/333] [splittiming] Log typo. --- src/NotesLoaderSMA.cpp | 2 +- src/NotesLoaderSSC.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index fb7d1fb11d..6963b98ac9 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -339,7 +339,7 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS if( seg.m_fWait < 0 ) { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, fWait %f.", fBeat, seg.m_fWait ); + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait ); continue; } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 8003a20754..116f4c1d98 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -159,7 +159,7 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) if( seg.m_fWait < 0 ) { - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, fWait %f.", fBeat, seg.m_fWait ); + LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait ); continue; } From cdd43f77f4ec4715e725619c0e54815552481c31 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 15:37:46 -0400 Subject: [PATCH 214/333] [splittiming] Display Speeds in Step Timing. --- Docs/Changelog_SSCformat.txt | 1 + Docs/Changelog_sm5.txt | 5 +++++ Themes/_fallback/metrics.ini | 9 ++++++--- src/NoteField.cpp | 34 +++++++++++++++++++++++++++++++++- src/NoteField.h | 1 + 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index fb04d68912..baa1f8ecc7 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -11,6 +11,7 @@ ________________________________________________________________________________ [v0.7] - theDtTvB, Wolfman2000 * Split Timing officially implemented. +* #SPEEDS tag for modified scroll speeds. [v0.59] - Wolfman2000 * Typo fix: #RADARVALUES needed a semicolon at the end, not a colon. diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index daf91cd16f..fccd9d9425 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,11 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/15 +---------- +* Added #SPEEDS to the SSC format. This multiplies your scrolling speed during + gameplay, not replaces it (see mod attacks for replacing). [Wolfman2000] + 2011/05/14 ---------- * [ModIcon] Added StopWords metric. [AJ] diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 4be294753a..ed69511b12 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -989,6 +989,7 @@ TimeSignatureColor=color("1,0.55,0,1") TickcountColor=color("0,1,0,1") ComboColor=color("0.55,1,0,1") LabelColor=color("1,0,0,1") +SpeedColor=color("0.5,1,1,1") # BPMIsLeftSide=true StopIsLeftSide=true @@ -998,15 +999,17 @@ TimeSignatureIsLeftSide=true TickcountIsLeftSide=false ComboIsLeftSide=false LabelIsLeftSide=false +SpeedIsLeftSide=false # BPMOffsetX=60 StopOffsetX=50 DelayOffsetX=120 WarpOffsetX=60 TimeSignatureOffsetX=30 -TickcountOffsetX=10 -ComboOffsetX=30 -LabelOffsetX=80 +TickcountOffsetX=105 +ComboOffsetX=95 +LabelOffsetX=120 +SpeedOffsetX=30 [PlayerStageStats] # Original CVS Grading diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 6982277071..c3aa03708c 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -454,6 +454,7 @@ static ThemeMetric TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignature static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); static ThemeMetric LABEL_COLOR ( "NoteField", "LabelColor" ); +static ThemeMetric SPEED_COLOR ( "NoteField", "SpeedColor" ); static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); @@ -462,6 +463,7 @@ static ThemeMetric TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatu static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" ); static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); static ThemeMetric LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" ); +static ThemeMetric SPEED_IS_LEFT_SIDE ( "NoteField", "SpeedIsLeftSide" ); static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); @@ -470,7 +472,7 @@ static ThemeMetric TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOf static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); static ThemeMetric LABEL_OFFSETX ( "NoteField", "LabelOffsetX" ); - +static ThemeMetric SPEED_OFFSETX ( "NoteField", "SpeedOffsetX" ); void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { @@ -600,6 +602,23 @@ void NoteField::DrawLabelText( const float fBeat, RString sLabel ) m_textMeasureNumber.Draw(); } +void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait ) +{ + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); + const float xBase = GetWidth()/2.f; + const float xOffset = SPEED_OFFSETX * fZoom; + + m_textMeasureNumber.SetZoom( fZoom ); + m_textMeasureNumber.SetHorizAlign( SPEED_IS_LEFT_SIDE ? align_right : align_left ); + m_textMeasureNumber.SetDiffuse( SPEED_COLOR ); + m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + m_textMeasureNumber.SetText( ssprintf("%.6f\n--\n%.6f", fPercent, fWait) ); + m_textMeasureNumber.SetXY( (SPEED_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.Draw(); +} + void NoteField::DrawAttackText( const float fBeat, const Attack &attack ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); @@ -913,6 +932,19 @@ void NoteField::DrawPrimitives() DrawLabelText( fBeat, seg->m_sLabel ); } } + + if( GAMESTATE->m_bIsEditorStepTiming ) + { + FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, seg ) + { + if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + { + float fBeat = NoteRowToBeat(seg->m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawSpeedText( fBeat, seg->m_fPercent, seg->m_fWait ); + } + } + } // Course mods text const Course *pCourse = GAMESTATE->m_pCurCourse; diff --git a/src/NoteField.h b/src/NoteField.h index c389676cfb..5cd582b322 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -64,6 +64,7 @@ protected: void DrawTickcountText( const float fBeat, int iTicks ); void DrawComboText( const float fBeat, int iCombo ); void DrawLabelText( const float fBeat, RString sLabel ); + void DrawSpeedText( const float fBeat, float fPercent, float fWait ); void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; From 466f0be35a898a16164fd5581d83800d00b92ee9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 15:53:20 -0400 Subject: [PATCH 215/333] [splittiming] ScreenEdit + Speeds Now let's try to implement the darn things. --- Themes/_fallback/Languages/en.ini | 4 +++ src/ScreenEdit.cpp | 44 ++++++++++++++++++++++++++++++- src/ScreenEdit.h | 3 +++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 5221f213de..cca665ecc4 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -852,6 +852,8 @@ Edit tickcount=Edit tickcount Edit combo=Edit combo Edit label=Edit label Edit warp=Edit warp +Edit speed (percent)=Edit speed (percent) +Edit speed (wait)=Edit speed (wait in beats) Editor options=Options EditorShowBGChangesPlay=Show Backgrounds Erase step timing=Erase step timing @@ -1227,6 +1229,8 @@ Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. Enter a new Label value.=Enter a name for this section of the chart. Enter a new Warp value.=Enter the beat you will warp to when you reach this point. +Enter a new Speed percent value.=Enter the ratio for speed scrolling. 1 is the default. +Enter a new Speed wait value.=Enter how long in beats it takes to change. 0 is instant. Are you sure you want to erase this chart's timing data?=Are you sure you want to erase this chart's timing data? Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 38ff20c18a..aba80b9090 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -83,6 +83,8 @@ AutoScreenMessage( SM_BackFromTickcountChange ); AutoScreenMessage( SM_BackFromComboChange ); AutoScreenMessage( SM_BackFromLabelChange ); AutoScreenMessage( SM_BackFromWarpChange ); +AutoScreenMessage( SM_BackFromSpeedPercentChange ); +AutoScreenMessage( SM_BackFromSpeedWaitChange ); AutoScreenMessage( SM_DoEraseStepTiming ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); @@ -576,7 +578,9 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::speed_percent, "Edit speed (percent)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::speed_wait, "Edit speed (wait)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -2759,6 +2763,22 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) GetAppropriateTiming().SetWarpAtBeat( GetBeat(), fWarp ); SetDirty( true ); } + else if( SM == SM_BackFromSpeedPercentChange ) + { + float fNum = StringToFloat( ScreenTextEntry::s_sLastAnswer ); + GetAppropriateTiming().SetSpeedPercentAtBeat( GetBeat(), fNum ); + SetDirty( true ); + } + else if ( SM == SM_BackFromSpeedWaitChange ) + { + float fDen = StringToFloat( ScreenTextEntry::s_sLastAnswer ); + if( fDen >= 0) + { + GetAppropriateTiming().SetSpeedWaitAtBeat( GetBeat(), fDen ); + } + SetDirty( true ); + } + else if( SM == SM_BackFromBGChange ) { HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers ); @@ -3176,10 +3196,14 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedPercentAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedWaitAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsEditorStepTiming; EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } @@ -3858,6 +3882,8 @@ static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tick static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." ); static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." ); +static LocalizedString ENTER_SPEED_PERCENT_VALUE ( "ScreenEdit", "Enter a new Speed percent value." ); +static LocalizedString ENTER_SPEED_WAIT_VALUE ( "ScreenEdit", "Enter a new Speed wait value." ); static LocalizedString CONFIRM_TIMING_ERASE ( "ScreenEdit", "Are you sure you want to erase this chart's timing data?" ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { @@ -3941,6 +3967,22 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 10 ); break; + case speed_percent: + ScreenTextEntry::TextEntry( + SM_BackFromSpeedPercentChange, + ENTER_SPEED_PERCENT_VALUE, + ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fPercent ), + 10 + ); + break; + case speed_wait: + ScreenTextEntry::TextEntry( + SM_BackFromSpeedWaitChange, + ENTER_SPEED_WAIT_VALUE, + ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fWait ), + 10 + ); + break; case erase_step_timing: ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); break; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 68eabff5f5..0f31a3e759 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -496,6 +496,9 @@ public: tickcount, combo, warp, +// speed, + speed_percent, + speed_wait, erase_step_timing, NUM_TIMING_DATA_INFORMATION_CHOICES }; From 6db40f034aa5f671e5223f92dcb43719002c7cbc Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 16:07:18 -0400 Subject: [PATCH 216/333] [splittiming] Core lines set for #SPEEDS. Let's see how badly this breaks. --- src/ArrowEffects.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index e6f3831849..15ea4eb0c0 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -230,7 +230,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float float fSongBeat = position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; - fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); + fYOffset += GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetSpeedPercentAtBeat( fNoteBeat ) * + fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); } if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) @@ -241,7 +242,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; float fBPS = fBPM/60.f; float fYOffsetTimeSpacing = fSecondsUntilStep * fBPS; - fYOffset += fYOffsetTimeSpacing * pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; + fYOffset += GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetSpeedPercentAtBeat( fNoteBeat ) * + fYOffsetTimeSpacing * pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; } // TODO: If we allow noteskins to have metricable row spacing From 59febf0c2736078734bd2a5352f7a90abac5479c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 16:13:56 -0400 Subject: [PATCH 217/333] [splittiming] Adjusted too much there. --- Themes/_fallback/metrics.ini | 8 ++++---- src/NoteField.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index ed69511b12..867f07e5fe 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1004,11 +1004,11 @@ SpeedIsLeftSide=false BPMOffsetX=60 StopOffsetX=50 DelayOffsetX=120 -WarpOffsetX=60 +WarpOffsetX=70 TimeSignatureOffsetX=30 -TickcountOffsetX=105 -ComboOffsetX=95 -LabelOffsetX=120 +TickcountOffsetX=50 +ComboOffsetX=30 +LabelOffsetX=130 SpeedOffsetX=30 [PlayerStageStats] diff --git a/src/NoteField.cpp b/src/NoteField.cpp index c3aa03708c..f94cb62e9e 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -614,7 +614,7 @@ void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait ) m_textMeasureNumber.SetHorizAlign( SPEED_IS_LEFT_SIDE ? align_right : align_left ); m_textMeasureNumber.SetDiffuse( SPEED_COLOR ); m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%.6f\n--\n%.6f", fPercent, fWait) ); + m_textMeasureNumber.SetText( ssprintf("%.3f\n--\n%.3f", fPercent, fWait) ); m_textMeasureNumber.SetXY( (SPEED_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); m_textMeasureNumber.Draw(); } From 11de86e2601b2c52e568433e1d822a3c795bb0e0 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 16:40:06 -0400 Subject: [PATCH 218/333] [splittiming] Right, LOAD the #SPEEDS. --- src/NotesLoaderSMA.cpp | 4 +++- src/NotesLoaderSSC.cpp | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 6963b98ac9..6acec86ced 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -667,7 +667,9 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else if( sValueName=="SPEED" ) { - ; // This is something we should consider implementing. + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessSpeeds( timing, iRowsPerBeat, sParams[1] ); } else if( sValueName=="MULTIPLIER" ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 116f4c1d98..68a2886042 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -558,6 +558,11 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach ProcessWarps(stepsTiming, sParams[1]); } + else if( sValueName=="SPEED" ) + { + ProcessSpeeds( stepsTiming, sParams[1] ); + } + else if( sValueName=="LABELS" ) { ProcessLabels(stepsTiming, sParams[1]); From c25c9616d965314b23b4aa90b62ae4227b967d99 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 16:42:50 -0400 Subject: [PATCH 219/333] [splittiming] Minor fix. --- Themes/_fallback/metrics.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 867f07e5fe..3189c3444e 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1004,10 +1004,10 @@ SpeedIsLeftSide=false BPMOffsetX=60 StopOffsetX=50 DelayOffsetX=120 -WarpOffsetX=70 +WarpOffsetX=90 TimeSignatureOffsetX=30 -TickcountOffsetX=50 -ComboOffsetX=30 +TickcountOffsetX=70 +ComboOffsetX=50 LabelOffsetX=130 SpeedOffsetX=30 From a0d3d9d6ee4febdbce4ab8c9e4f8e75950cb5f4c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 16:56:35 -0400 Subject: [PATCH 220/333] [splittiming] SPEEDS! --- src/NotesLoaderSSC.cpp | 2 +- src/NotesWriterSSC.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 68a2886042..e01e4dd774 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -558,7 +558,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach ProcessWarps(stepsTiming, sParams[1]); } - else if( sValueName=="SPEED" ) + else if( sValueName=="SPEEDS" ) { ProcessSpeeds( stepsTiming, sParams[1] ); } diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3d036c538c..d65ddc9f13 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -136,7 +136,7 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo { w.Init( "SPEEDS" ); FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) - w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait ); + w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait ); w.Finish(); } From 87ac80c33fb36587cb697e91652096736a6cb713 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 17:14:18 -0400 Subject: [PATCH 221/333] [splittiming] We know this doesn't work. Time to find what does. --- src/ArrowEffects.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 15ea4eb0c0..e6f3831849 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -230,8 +230,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float float fSongBeat = position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; - fYOffset += GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetSpeedPercentAtBeat( fNoteBeat ) * - fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); + fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); } if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) @@ -242,8 +241,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; float fBPS = fBPM/60.f; float fYOffsetTimeSpacing = fSecondsUntilStep * fBPS; - fYOffset += GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetSpeedPercentAtBeat( fNoteBeat ) * - fYOffsetTimeSpacing * pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; + fYOffset += fYOffsetTimeSpacing * pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing; } // TODO: If we allow noteskins to have metricable row spacing From 231f9433c3b360267955b884ca6b58b72e871ee3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 17:39:57 -0400 Subject: [PATCH 222/333] [splittiming] Speed Changes working...somewhat. There needs to be some more math involving the beats. --- src/ArrowEffects.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index e6f3831849..f8de8cfbdd 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -222,12 +222,15 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float float fYOffset = 0; const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsEditorStepTiming) ? pPlayerState->m_Position : GAMESTATE->m_Position; + + float fSongBeat = position.m_fSongBeatVisible; + + Steps *pCurSteps = GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]; /* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or * entirely time spacing (respectively). Occasionally, we tween between them. */ if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 1.0f ) { - float fSongBeat = position.m_fSongBeatVisible; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); @@ -235,8 +238,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) { - float fSongSeconds = position.m_fMusicSecondsVisible; - float fNoteSeconds = GAMESTATE->m_pCurSteps[pPlayerState->m_PlayerNumber]->m_Timing.GetElapsedTimeFromBeat(fNoteBeat); + float fSongSeconds = GAMESTATE->m_Position.m_fMusicSecondsVisible; + float fNoteSeconds = pCurSteps->m_Timing.GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; float fBPM = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollBPM; float fBPS = fBPM/60.f; @@ -246,7 +249,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float // TODO: If we allow noteskins to have metricable row spacing // (per issue 24), edit this to reflect that. -aj - fYOffset *= ARROW_SPACING; + fYOffset *= ARROW_SPACING * pCurSteps->m_Timing.GetSpeedPercentAtBeat( fSongBeat ); // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) @@ -293,6 +296,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float // Factor in scroll speed float fScrollSpeed = pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollSpeed; + if( pPlayerState->m_PlayerOptions.GetCurrent().m_fRandomSpeed > 0 && !bAbsolute ) { // Generate a deterministically "random" speed for each arrow. From 300360a6125367af7d80d878de87e32b8fb8ee30 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 17:45:21 -0400 Subject: [PATCH 223/333] [splittiming] Setup for math fun. Feels like we're doing trig or calculus here. --- src/ArrowEffects.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index f8de8cfbdd..3224b0cb76 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -249,8 +249,15 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float // TODO: If we allow noteskins to have metricable row spacing // (per issue 24), edit this to reflect that. -aj - fYOffset *= ARROW_SPACING * pCurSteps->m_Timing.GetSpeedPercentAtBeat( fSongBeat ); - + fYOffset *= ARROW_SPACING; + + // Factor in the SpeedSegment. + SpeedSegment &seg = pCurSteps->m_Timing.GetSpeedSegmentAtBeat( fSongBeat ); + if( seg.m_fPercent != 1 && fSongBeat + seg.m_fWait <= fNoteBeat ) + { + // Math here. + fYOffset *= pCurSteps->m_Timing.GetSpeedPercentAtBeat( fSongBeat ); + } // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) return fYOffset * pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollSpeed; From e9bcdc5568980d584cc43c6713d43c5ad95f4b3a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 18:15:52 -0400 Subject: [PATCH 224/333] [splittiming] Kind of getting there... --- src/ArrowEffects.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 3224b0cb76..9e96ee8111 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -253,10 +253,23 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float // Factor in the SpeedSegment. SpeedSegment &seg = pCurSteps->m_Timing.GetSpeedSegmentAtBeat( fSongBeat ); - if( seg.m_fPercent != 1 && fSongBeat + seg.m_fWait <= fNoteBeat ) + if( seg.m_fPercent != 1 ) { - // Math here. - fYOffset *= pCurSteps->m_Timing.GetSpeedPercentAtBeat( fSongBeat ); + if( fSongBeat + seg.m_fWait <= fNoteBeat ) + { + float fBeatsUsed = fSongBeat - NoteRowToBeat(seg.m_iStartRow); + float fRatioUsed = fBeatsUsed / seg.m_fWait; + + float fDistance = 1 - seg.m_fPercent; + + float fRatioNeed = fRatioUsed * fDistance; + + fYOffset *= (1 + fRatioNeed); + } + else + { + fYOffset *= seg.m_fPercent; + } } // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) From eb5ae94f070ae0cd624c2925e19fadc8fd1f1527 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 18:33:47 -0400 Subject: [PATCH 225/333] [splittiming] Follow Daisu's lua a little more. --- src/ArrowEffects.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 9e96ee8111..3fe128a777 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -255,9 +255,11 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float SpeedSegment &seg = pCurSteps->m_Timing.GetSpeedSegmentAtBeat( fSongBeat ); if( seg.m_fPercent != 1 ) { - if( fSongBeat + seg.m_fWait <= fNoteBeat ) + float fStartBeat = NoteRowToBeat(seg.m_iStartRow); + + if( fStartBeat + seg.m_fWait >= fSongBeat ) { - float fBeatsUsed = fSongBeat - NoteRowToBeat(seg.m_iStartRow); + float fBeatsUsed = fSongBeat - fStartBeat; float fRatioUsed = fBeatsUsed / seg.m_fWait; float fDistance = 1 - seg.m_fPercent; From b8c3910bd18b2da71b91f144041ca05f70da5de8 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sun, 15 May 2011 17:43:35 -0500 Subject: [PATCH 226/333] revert changes here to prevent the random theme bug --- src/ScreenOptionsMasterPrefs.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 6ef345ceaf..347ecf041d 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -181,7 +181,7 @@ static void GameSel( int &sel, bool ToSel, const ConfOption *pConfOption ) sel = 0; for(unsigned i = 0; i < choices.size(); ++i) - if( !choices[i].EqualsNoCase(sCurGameName) ) + if( !stricmp(choices[i], sCurGameName) ) sel = i; } else { vector aGames; @@ -222,12 +222,12 @@ static void Language( int &sel, bool ToSel, const ConfOption *pConfOption ) { sel = -1; for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) - if( !vs[i].EqualsNoCase(THEME->GetCurLanguage()) ) + if( !stricmp(vs[i], THEME->GetCurLanguage()) ) sel = i; // If the current language doesn't exist, we'll show BASE_LANGUAGE, so select that. for( unsigned i=0; sel == -1 && i < vs.size(); ++i ) - if( !vs[i].EqualsNoCase(SpecialFiles::BASE_LANGUAGE) ) + if( !stricmp(vs[i], SpecialFiles::BASE_LANGUAGE) ) sel = i; if( sel == -1 ) @@ -276,7 +276,7 @@ static void RequestedTheme( int &sel, bool ToSel, const ConfOption *pConfOption { sel = 0; for( unsigned i=1; im_sTheme.Get()) ) + if( !stricmp(vsThemeNames[i], PREFSMAN->m_sTheme.Get()) ) sel = i; } else @@ -302,7 +302,7 @@ static void Announcer( int &sel, bool ToSel, const ConfOption *pConfOption ) { sel = 0; for( unsigned i=1; iGetCurAnnouncerName()) ) + if( !stricmp(choices[i], ANNOUNCER->GetCurAnnouncerName()) ) sel = i; } else @@ -329,7 +329,7 @@ static void DefaultNoteSkin( int &sel, bool ToSel, const ConfOption *pConfOption po.FromString( PREFSMAN->m_sDefaultModifiers ); sel = 0; for( unsigned i=0; i < choices.size(); i++ ) - if( !choices[i].EqualsNoCase(po.m_sNoteSkin) ) + if( !stricmp(choices[i], po.m_sNoteSkin) ) sel = i; } else From 183e74553433312ac9d103148131129c1c8092db Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 18:57:04 -0400 Subject: [PATCH 227/333] [splittiming] Of course...negative inverse. --- src/ArrowEffects.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 3fe128a777..1db9a40903 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -261,11 +261,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float { float fBeatsUsed = fSongBeat - fStartBeat; float fRatioUsed = fBeatsUsed / seg.m_fWait; - float fDistance = 1 - seg.m_fPercent; - - float fRatioNeed = fRatioUsed * fDistance; - + float fRatioNeed = fRatioUsed * -fDistance; fYOffset *= (1 + fRatioNeed); } else From f36121e6479180ab34683e634733f277d945817e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 19:39:14 -0400 Subject: [PATCH 228/333] [splittiming] Remember transitions to 1x. --- src/ArrowEffects.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 1db9a40903..1719b7e1dc 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -252,18 +252,23 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fYOffset *= ARROW_SPACING; // Factor in the SpeedSegment. - SpeedSegment &seg = pCurSteps->m_Timing.GetSpeedSegmentAtBeat( fSongBeat ); - if( seg.m_fPercent != 1 ) + TimingData &tim = pCurSteps->m_Timing; + + const int index = tim.GetSpeedSegmentIndexAtBeat( fSongBeat ); + if( index > 0 ) { + SpeedSegment &seg = tim.GetSpeedSegmentAtBeat( fSongBeat ); float fStartBeat = NoteRowToBeat(seg.m_iStartRow); if( fStartBeat + seg.m_fWait >= fSongBeat ) { + const float fPriorSpeed = tim.m_SpeedSegments[index - 1].m_fPercent; float fBeatsUsed = fSongBeat - fStartBeat; float fRatioUsed = fBeatsUsed / seg.m_fWait; - float fDistance = 1 - seg.m_fPercent; + + float fDistance = fPriorSpeed - seg.m_fPercent; float fRatioNeed = fRatioUsed * -fDistance; - fYOffset *= (1 + fRatioNeed); + fYOffset *= (fPriorSpeed + fRatioNeed); } else { From c830bf81fe10eb291fca27bb4ab402a8c5529386 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 21:15:53 -0400 Subject: [PATCH 229/333] [splittiming] Attempt at Speed Segment control. Working on another fix, will test this second. --- src/ScreenEdit.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index aba80b9090..31f6da17fd 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2438,7 +2438,7 @@ void ScreenEdit::TransitionEditState( EditState em ) // Restore the cursor position + Quantize + Clamp SetBeat( max( 0, Quantize( m_fBeatToReturnTo, NoteTypeToBeat(m_SnapDisplay.GetNoteType()) ) ) ); - + GAMESTATE->m_bInStepEditor = true; break; case STATE_PLAYING: @@ -2458,10 +2458,11 @@ void ScreenEdit::TransitionEditState( EditState em ) // XXX // GAMESTATE->ResetNoteSkins(); //GAMESTATE->res - + GAMESTATE->m_bInStepEditor = false; break; } case STATE_RECORDING_PAUSED: + GAMESTATE->m_bInStepEditor = false; break; } From 58b209959f737f9c658d0470b4291a888fe097f9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 21:22:17 -0400 Subject: [PATCH 230/333] [splittiming] Fix minor load issue on SPEEDS. --- src/NotesLoaderSMA.cpp | 4 ++-- src/NotesLoaderSSC.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 6acec86ced..ba85057746 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -316,9 +316,9 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS vector vs2; split( *s1, "=", vs2 ); - if( vs2[0] == 0 ) // First one always seems to have 2. + if( RowToBeat(vs2[0], iRowsPerBeat) == 0 ) // First one always seems to have 2. { - vs2.push_back(0); + vs2.push_back("0"); } if( vs2.size() < 3 ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index e01e4dd774..1803b03f51 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -138,7 +138,7 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) if( vs2[0] == 0 ) // First one always seems to have 2. { - vs2.push_back(0); + vs2.push_back("0"); } if( vs2.size() < 3 ) From 275bb63ca0dd203f2c7d6a15aedb7f42e509ac67 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 21:24:39 -0400 Subject: [PATCH 231/333] [splittiming] Don't show SPEEDS in pure editor. --- src/ArrowEffects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 1719b7e1dc..047a5331af 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -255,7 +255,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float TimingData &tim = pCurSteps->m_Timing; const int index = tim.GetSpeedSegmentIndexAtBeat( fSongBeat ); - if( index > 0 ) + if( !GAMESTATE->m_bInStepEditor && index > 0 ) { SpeedSegment &seg = tim.GetSpeedSegmentAtBeat( fSongBeat ); float fStartBeat = NoteRowToBeat(seg.m_iStartRow); From 059f0357ba5e6ba4eb9a275c7fbe5f849d441bdb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 21:28:44 -0400 Subject: [PATCH 232/333] [splittiming] Allow #COMBOS to be 0. --- src/TimingData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.h b/src/TimingData.h index d68e2ec98e..9a4d67d6f1 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -508,7 +508,7 @@ struct ComboSegment * @param t the amount the combo increases on a succesful hit. */ ComboSegment( int s, int t ): m_iStartRow(max(0, s)), - m_iCombo(max(1,t)) {} + m_iCombo(max(0,t)) {} /** * @brief The row in which the ComboSegment activates. */ From 59bbc4f4bd9e63211bb0fbce35806d4b17707707 Mon Sep 17 00:00:00 2001 From: Flameshadowxeroshin Date: Sun, 15 May 2011 21:58:15 -0500 Subject: [PATCH 233/333] [splittiming] hey it's GetTimingData for freem --- src/Steps.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Steps.cpp b/src/Steps.cpp index 3174e011b2..2a877d545b 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -451,6 +451,12 @@ public: return 1; } + static int GetTimingData( T* p, lua_State *L ) + { + p->m_SongTiming.PushSelf(L); + return 1; + } + static int GetHash( T* p, lua_State *L ) { lua_pushnumber( L, p->GetHash() ); return 1; } // untested @@ -461,6 +467,7 @@ public: lua_pushstring( L, out ); return 1; } + LunaSteps() { @@ -473,6 +480,7 @@ public: ADD_METHOD( GetMeter ); ADD_METHOD( HasSignificantTimingChanges ); ADD_METHOD( GetRadarValues ); + ADD_METHOD( GetTimingData ); //ADD_METHOD( GetSMNoteData ); ADD_METHOD( GetStepsType ); ADD_METHOD( IsAnEdit ); From e2766cf644d1731376f7a44e464952cc0ac65569 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 23:48:03 -0400 Subject: [PATCH 234/333] [splittiming] SpeedSegments run on Seconds now. ScreenEdit's code probably needs to be redone. At least, someone find a way to remove "Beats" or "Seconds" from the text entry area. --- Themes/_fallback/Languages/en.ini | 10 +++-- src/ArrowEffects.cpp | 18 ++++++-- src/NoteField.cpp | 6 +-- src/NoteField.h | 2 +- src/NotesLoaderSMA.cpp | 10 ++++- src/NotesLoaderSSC.cpp | 9 +++- src/NotesWriterSSC.cpp | 4 +- src/ScreenEdit.cpp | 34 +++++++++++++++ src/ScreenEdit.h | 7 +++ src/TimingData.cpp | 34 ++++++++++++--- src/TimingData.h | 71 +++++++++++++++++++++++++++---- 11 files changed, 177 insertions(+), 28 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index cca665ecc4..4267bfe208 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -558,6 +558,7 @@ Baked Random=Baked Random Bar=Bar Battery=Battery Beat=Beat +Beats=Beats Big=Big Blind=Blind Blink=Blink @@ -694,6 +695,7 @@ Right=Right Roll=Roll Romanization=Transliterate SHOW=Show +Seconds=Seconds Select=Select Servers=Servers Shift Left=Shift Left @@ -853,7 +855,8 @@ Edit combo=Edit combo Edit label=Edit label Edit warp=Edit warp Edit speed (percent)=Edit speed (percent) -Edit speed (wait)=Edit speed (wait in beats) +Edit speed (wait)=Edit speed (length) +Edit speed (mode)=Edit speed (mode) Editor options=Options EditorShowBGChangesPlay=Show Backgrounds Erase step timing=Erase step timing @@ -1229,8 +1232,9 @@ Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. Enter a new Label value.=Enter a name for this section of the chart. Enter a new Warp value.=Enter the beat you will warp to when you reach this point. -Enter a new Speed percent value.=Enter the ratio for speed scrolling. 1 is the default. -Enter a new Speed wait value.=Enter how long in beats it takes to change. 0 is instant. +Enter a new Speed percent value.=Enter the ratio for speed scrolling.\n\n1 is the default scroll. +Enter a new Speed wait value.=Enter how long in seconds/beats it takes to change.\n\n0 is instant. +Enter a new Speed mode value.=Enter how this segment is handled.\n\nType "0" for beats, "1" for seconds. Are you sure you want to erase this chart's timing data?=Are you sure you want to erase this chart's timing data? Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 047a5331af..b2b6d60941 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -259,12 +259,24 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float { SpeedSegment &seg = tim.GetSpeedSegmentAtBeat( fSongBeat ); float fStartBeat = NoteRowToBeat(seg.m_iStartRow); + float fStartTime = tim.GetElapsedTimeFromBeat( fStartBeat ); + float fEndTime; - if( fStartBeat + seg.m_fWait >= fSongBeat ) + if( seg.m_usMode == 1 ) // seconds + { + fEndTime = fStartTime + seg.m_fWait; + } + else + { + fEndTime = tim.GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ); + } + float fCurTime = tim.GetElapsedTimeFromBeat( fSongBeat ); + + if( fEndTime >= fCurTime ) { const float fPriorSpeed = tim.m_SpeedSegments[index - 1].m_fPercent; - float fBeatsUsed = fSongBeat - fStartBeat; - float fRatioUsed = fBeatsUsed / seg.m_fWait; + float fTimeUsed = fCurTime - fStartTime; + float fRatioUsed = fTimeUsed / (fEndTime - fStartTime); float fDistance = fPriorSpeed - seg.m_fPercent; float fRatioNeed = fRatioUsed * -fDistance; diff --git a/src/NoteField.cpp b/src/NoteField.cpp index f94cb62e9e..1ad62d255b 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -602,7 +602,7 @@ void NoteField::DrawLabelText( const float fBeat, RString sLabel ) m_textMeasureNumber.Draw(); } -void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait ) +void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait, unsigned short usMode ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); @@ -614,7 +614,7 @@ void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait ) m_textMeasureNumber.SetHorizAlign( SPEED_IS_LEFT_SIDE ? align_right : align_left ); m_textMeasureNumber.SetDiffuse( SPEED_COLOR ); m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); - m_textMeasureNumber.SetText( ssprintf("%.3f\n--\n%.3f", fPercent, fWait) ); + m_textMeasureNumber.SetText( ssprintf("%.3f\n%s\n%.3f", fPercent, (usMode == 1 ? "S" : "B"), fWait) ); m_textMeasureNumber.SetXY( (SPEED_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); m_textMeasureNumber.Draw(); } @@ -941,7 +941,7 @@ void NoteField::DrawPrimitives() { float fBeat = NoteRowToBeat(seg->m_iStartRow); if( IS_ON_SCREEN(fBeat) ) - DrawSpeedText( fBeat, seg->m_fPercent, seg->m_fWait ); + DrawSpeedText( fBeat, seg->m_fPercent, seg->m_fWait, seg->m_usMode ); } } } diff --git a/src/NoteField.h b/src/NoteField.h index 5cd582b322..b3993fd6f6 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -64,7 +64,7 @@ protected: void DrawTickcountText( const float fBeat, int iTicks ); void DrawComboText( const float fBeat, int iCombo ); void DrawLabelText( const float fBeat, RString sLabel ); - void DrawSpeedText( const float fBeat, float fPercent, float fWait ); + void DrawSpeedText( const float fBeat, float fPercent, float fWait, unsigned short usMode ); void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index ba85057746..23dd584691 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -306,6 +306,11 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam ) } } +float BeatToSeconds(float fromBeat, RString toSomething) +{ + return 0; +} + void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam ) { vector vs1; @@ -329,7 +334,10 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS const float fBeat = RowToBeat( vs2[0], iRowsPerBeat ); - SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] )); + unsigned short tmp = ( (vs2[2].find("s") || vs2[2].find("S") ) + ? 1 : 0); + + SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), tmp); if( fBeat < 0 ) { diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 1803b03f51..352387e7df 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -141,7 +141,12 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) vs2.push_back("0"); } - if( vs2.size() < 3 ) + if( vs2.size() == 3 ) + { + vs2.push_back("0"); + } + + if( vs2.size() < 4 ) { LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with %i values.", (int)vs2.size() ); continue; @@ -149,7 +154,7 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) const float fBeat = StringToFloat( vs2[0] ); - SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] )); + SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), static_cast(StringToInt(vs2[3]))); if( fBeat < 0 ) { diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index d65ddc9f13..3b7c4ae729 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -77,6 +77,8 @@ struct TimingTagWriter { void Write( const int row, const int value ) { Write( row, ssprintf( "%d", value ) ); } void Write( const int row, const int a, const int b ) { Write( row, ssprintf( "%d=%d", a, b ) ); } void Write( const int row, const float a, const float b ) { Write( row, ssprintf( "%.6f=%.6f", a, b) ); } + void Write( const int row, const float a, const float b, const unsigned short c ) + { Write( row, ssprintf( "%.6f=%.6f=%hd", a, b, c) ); } void Init( const RString sTag ) { m_sNext = "#" + sTag + ":"; } void Finish( ) { m_pvsLines->push_back( ( m_sNext != "," ? m_sNext : "" ) + ";" ); } @@ -136,7 +138,7 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo { w.Init( "SPEEDS" ); FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) - w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait ); + w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode ); w.Finish(); } diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 31f6da17fd..0851795b87 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -85,6 +85,7 @@ AutoScreenMessage( SM_BackFromLabelChange ); AutoScreenMessage( SM_BackFromWarpChange ); AutoScreenMessage( SM_BackFromSpeedPercentChange ); AutoScreenMessage( SM_BackFromSpeedWaitChange ); +AutoScreenMessage( SM_BackFromSpeedModeChange ); AutoScreenMessage( SM_DoEraseStepTiming ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); @@ -580,6 +581,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::speed_percent, "Edit speed (percent)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::speed_wait, "Edit speed (wait)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::speed_mode, "Edit speed (mode)", true, EditMode_Full, true, true, 0, "Beats", "Seconds" ), MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) ); @@ -2779,6 +2781,19 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } SetDirty( true ); } + else if ( SM == SM_BackFromSpeedModeChange ) + { + int tmp = StringToInt(ScreenTextEntry::s_sLastAnswer ); + if( tmp == 0 ) + { + GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 0 ); + } + else + { + GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 1 ); + } + SetDirty( true ); + } else if( SM == SM_BackFromBGChange ) { @@ -3200,11 +3215,15 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedPercentAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedWaitAtBeat( fBeat ) ) ); + RString starting = ( pTime.GetSpeedModeAtBeat( fBeat ) == 1 ? "Seconds" : "Beats" ); + g_TimingDataInformation.rows[speed_mode].SetOneUnthemedChoice( starting.c_str() ); + g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsEditorStepTiming; EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } @@ -3885,6 +3904,7 @@ static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label va static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." ); static LocalizedString ENTER_SPEED_PERCENT_VALUE ( "ScreenEdit", "Enter a new Speed percent value." ); static LocalizedString ENTER_SPEED_WAIT_VALUE ( "ScreenEdit", "Enter a new Speed wait value." ); +static LocalizedString ENTER_SPEED_MODE_VALUE ( "ScreenEdit", "Enter a new Speed mode value." ); static LocalizedString CONFIRM_TIMING_ERASE ( "ScreenEdit", "Are you sure you want to erase this chart's timing data?" ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { @@ -3984,9 +4004,23 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 10 ); break; + case speed_mode: + { + RString sMode = ( GetAppropriateTiming().GetSpeedModeAtBeat( GetBeat() ) == 0 ? + "Beats" : "Seconds" ); + ScreenTextEntry::TextEntry( + SM_BackFromSpeedModeChange, + ENTER_SPEED_MODE_VALUE, + sMode.c_str(), + 10 + ); + + break; + } case erase_step_timing: ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); break; + } } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 0f31a3e759..e1e3bd4435 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -499,6 +499,7 @@ public: // speed, speed_percent, speed_wait, + speed_mode, erase_step_timing, NUM_TIMING_DATA_INFORMATION_CHOICES }; @@ -532,6 +533,12 @@ public: delete_change, NUM_BGCHANGE_CHOICES }; + + enum SpeedSegmentModes + { + SSMODE_Beats, + SSMODE_Seconds + }; /** * @brief Take care of any background changes that the user wants. diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 45302128b8..3fc509fab4 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -255,7 +255,7 @@ void TimingData::SetLabelAtRow( int iRow, const RString sLabel ) } } -void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait ) +void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait, unsigned short usMode ) { unsigned i; for( i = 0; i < m_SpeedSegments.size(); i++ ) @@ -268,31 +268,48 @@ void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait ) { if( i == 0 || ( m_SpeedSegments[i-1].m_fPercent != fPercent - || m_SpeedSegments[i-1].m_fWait != fWait ) ) - AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait) ); + || m_SpeedSegments[i-1].m_fWait != fWait + || m_SpeedSegments[i-1].m_usMode != usMode ) ) + AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait, usMode) ); } else { if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent - && m_SpeedSegments[i-1].m_fWait == fWait ) + && m_SpeedSegments[i-1].m_fWait == fWait + && m_SpeedSegments[i-1].m_usMode == usMode ) m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); else { m_SpeedSegments[i].m_fPercent = fPercent; m_SpeedSegments[i].m_fWait = fWait; + m_SpeedSegments[i].m_usMode = usMode; } } } void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent ) { - SetSpeedAtRow( iRow, fPercent, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait ); + SetSpeedAtRow( iRow, + fPercent, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode); } void TimingData::SetSpeedWaitAtRow( int iRow, float fWait ) { - SetSpeedAtRow( iRow, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, fWait ); + SetSpeedAtRow( iRow, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, + fWait, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode); +} + +void TimingData::SetSpeedModeAtRow( int iRow, unsigned short usMode ) +{ + SetSpeedAtRow( iRow, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait, + usMode ); } @@ -351,6 +368,11 @@ float TimingData::GetSpeedWaitAtRow( int iRow ) return GetSpeedSegmentAtRow( iRow ).m_fWait; } +unsigned short TimingData::GetSpeedModeAtRow( int iRow ) +{ + return GetSpeedSegmentAtRow( iRow ).m_usMode; +} + // Multiply the BPM in the range [fStartBeat,fEndBeat) by fFactor. void TimingData::MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ) { diff --git a/src/TimingData.h b/src/TimingData.h index 9a4d67d6f1..b24cccdc5a 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -660,20 +660,22 @@ struct LabelSegment struct SpeedSegment { /** @brief Sets up the SpeedSegment with default values. */ - SpeedSegment(): m_iStartRow(0), m_fPercent(1), m_fWait(0) {} + SpeedSegment(): m_iStartRow(0), + m_fPercent(1), m_fWait(0), m_usMode(0) {} /** * @brief Sets up the SpeedSegment with specified values. * @param i The row this activates. * @param p The percentage to use. */ - SpeedSegment(int i, float p): m_iStartRow(0), m_fPercent(p), m_fWait(0) {} + SpeedSegment(int i, float p): m_iStartRow(0), + m_fPercent(p), m_fWait(0), m_usMode(0) {} /** * @brief Sets up the SpeedSegment with specified values. * @param r The beat this activates. * @param p The percentage to use. */ SpeedSegment(float r, float p): m_iStartRow(BeatToNoteRow(r)), - m_fPercent(p), m_fWait(0) {} + m_fPercent(p), m_fWait(0), m_usMode(0) {} /** * @brief Sets up the SpeedSegment with specified values. @@ -681,7 +683,7 @@ struct SpeedSegment * @param p The percentage to use. * @param w The number of beats to wait. */ SpeedSegment(int i, float p, float w): m_iStartRow(i), - m_fPercent(p), m_fWait(w) {} + m_fPercent(p), m_fWait(w), m_usMode(0) {} /** * @brief Sets up the SpeedSegment with specified values. @@ -689,17 +691,43 @@ struct SpeedSegment * @param p The percentage to use. * @param w The number of beats to wait. */ SpeedSegment(float r, float p, float w): m_iStartRow(BeatToNoteRow(r)), - m_fPercent(p), m_fWait(w) {} + m_fPercent(p), m_fWait(w), m_usMode(0) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param i The row this activates. + * @param p The percentage to use. + * @param w The number of beats/seconds to wait. + * @param k The mode used for the wait variable. */ + SpeedSegment(int i, float p, float w, unsigned short k): m_iStartRow(i), + m_fPercent(p), m_fWait(w), m_usMode(k) {} + + /** + * @brief Sets up the SpeedSegment with specified values. + * @param r The beat this activates. + * @param p The percentage to use. + * @param w The number of beats/seconds to wait. + * @param k The mode used for the wait variable.*/ + SpeedSegment(float r, float p, float w, unsigned short k): m_iStartRow(BeatToNoteRow(r)), + m_fPercent(p), m_fWait(w), m_usMode(k) {} /** @brief The row in which the ComboSegment activates. */ int m_iStartRow; /** @brief The percentage to use when multiplying the Player's BPM. */ float m_fPercent; /** - * @brief The number of beats to wait for the change to take place. + * @brief The number of beats or seconds to wait for the change to take place. * * A value of 0 means this is immediate. */ float m_fWait; + /** + * @brief The mode that this segment uses for the math. + * + * 0: beats + * 1: seconds + * other + */ + unsigned short m_usMode; /** * @brief Compares two SpeedSegments to see if they are equal to each other. @@ -710,6 +738,7 @@ struct SpeedSegment { COMPARE( m_iStartRow ); COMPARE( m_fPercent ); + COMPARE( m_usMode ); COMPARE( m_fWait ); return true; } @@ -1364,20 +1393,34 @@ public: * @return the wait. */ float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the Speed's mode at the given row. + * @param iNoteRow the row in question. + * @return the mode. + */ + unsigned short GetSpeedModeAtRow( int iNoteRow ); + /** + * @brief Retrieve the Speed's mode at the given beat. + * @param fBeat the beat in question. + * @return the mode. + */ + unsigned short GetSpeedModeAtBeat( float fBeat ) { return GetSpeedModeAtRow( BeatToNoteRow(fBeat) ); } /** * @brief Set the row to have the new Speed. * @param iNoteRow the row to have the new Speed. * @param fPercent the percent. * @param fWait the wait. + * @param usMode the mode. */ - void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait ); + void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait, unsigned short usMode ); /** * @brief Set the beat to have the new Speed. * @param fBeat the beat to have the new Speed. * @param fPercent the percent. * @param fWait the wait. + * @param usMode the mode. */ - void SetSpeedAtBeat( float fBeat, float fPercent, float fWait ) { SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait ); } + void SetSpeedAtBeat( float fBeat, float fPercent, float fWait, unsigned short usMode ) { SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait, usMode ); } /** * @brief Set the row to have the new Speed percent. * @param iNoteRow the row to have the new Speed percent. @@ -1402,6 +1445,18 @@ public: * @param fWait the wait. */ void SetSpeedWaitAtBeat( float fBeat, float fWait ) { SetSpeedWaitAtRow( BeatToNoteRow(fBeat), fWait); } + /** + * @brief Set the row to have the new Speed mode. + * @param iNoteRow the row to have the new Speed mode. + * @param usMode the mode. + */ + void SetSpeedModeAtRow( int iNoteRow, unsigned short usMode ); + /** + * @brief Set the beat to have the new Speed mode. + * @param fBeat the beat to have the new Speed mode. + * @param usMode the mode. + */ + void SetSpeedModeAtBeat( float fBeat, unsigned short usMode ) { SetSpeedModeAtRow( BeatToNoteRow(fBeat), usMode); } /** * @brief Retrieve the SpeedSegment at the specified row. * @param iNoteRow the row that has a SpeedSegment. From d71c547da082fe81a902a12896cc1841e815d3ea Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Mon, 16 May 2011 00:07:06 -0500 Subject: [PATCH 235/333] [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) Lua binding. --- Docs/Changelog_sm5.txt | 5 +++++ src/ProfileManager.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 91fb2ccaf9..b5c710aa47 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,11 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/16 +---------- +* [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) + Lua binding. [AJ] + 2011/05/15 ---------- * [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and diff --git a/src/ProfileManager.cpp b/src/ProfileManager.cpp index 812db73a8c..39821a75e1 100644 --- a/src/ProfileManager.cpp +++ b/src/ProfileManager.cpp @@ -833,6 +833,7 @@ public: static int GetNumLocalProfiles( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumLocalProfiles() ); return 1; } static int GetProfileDir( T* p, lua_State *L ) { lua_pushstring(L, p->GetProfileDir(Enum::Check(L, 1)) ); return 1; } static int IsSongNew( T* p, lua_State *L ) { lua_pushboolean(L, p->IsSongNew(Luna::check(L,1)) ); return 1; } + static int ProfileWasLoadedFromMemoryCard( T* p, lua_State *L ) { lua_pushboolean(L, p->ProfileWasLoadedFromMemoryCard(Enum::Check(L, 1)) ); return 1; } LunaProfileManager() { @@ -847,6 +848,7 @@ public: ADD_METHOD( GetNumLocalProfiles ); ADD_METHOD( GetProfileDir ); ADD_METHOD( IsSongNew ); + ADD_METHOD( ProfileWasLoadedFromMemoryCard ); } }; From 7670b922ad7e75280bb3dda36dfc3f680e423644 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Mon, 16 May 2011 00:11:09 -0500 Subject: [PATCH 236/333] update luadoc --- Docs/Luadoc/LuaDocumentation.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 39df9f4188..aa4e3c09fe 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -1626,12 +1626,11 @@ - - Return the Edit Local or nil if - it does not exist. + Return the Edit Local (during Profile editing) + or nil if it does not exist. - + Returns the ID of the Edit Local (during Profile editing). Return the source for the editor or nil From f8f47c002bf38259e28b02611ace602265bee68a Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 12:17:54 +0700 Subject: [PATCH 237/333] [splittiming] speed segment changes: - allow first speed segment to take effect - make speed segments take effect before delays - make speed segments not affect cmods --- src/ArrowEffects.cpp | 79 +++++++++++++++++++++++--------------------- src/GameState.cpp | 3 +- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index b2b6d60941..318bd75e01 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -211,6 +211,46 @@ void ArrowEffects::Update() } } +float GetSpeedMultiplier( float fSongBeat, float fMusicSeconds, const TimingData &tim ) +{ + if( tim.m_SpeedSegments.size() == 0 ) + return 1.0; + + const int index = tim.GetSpeedSegmentIndexAtBeat( fSongBeat ); + + const SpeedSegment &seg = tim.m_SpeedSegments[index]; + float fStartBeat = NoteRowToBeat(seg.m_iStartRow); + float fStartTime = tim.GetElapsedTimeFromBeat( fStartBeat ) - tim.GetDelayAtBeat( fStartBeat ); + float fEndTime; + float fCurTime = fMusicSeconds; + + if( seg.m_usMode == 1 ) // seconds + { + fEndTime = fStartTime + seg.m_fWait; + } + else + { + fEndTime = tim.GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - tim.GetDelayAtBeat( fStartBeat + seg.m_fWait ); + } + + if( fEndTime >= fCurTime && ( index > 0 || tim.m_SpeedSegments[0].m_fWait > 0.0 ) ) + { + const float fPriorSpeed = ( index == 0 ? 1 : tim.m_SpeedSegments[index - 1].m_fPercent ); + float fTimeUsed = fCurTime - fStartTime; + float fDuration = fEndTime - fStartTime; + float fRatioUsed = fDuration == 0.0 ? 1 : fTimeUsed / fDuration; + + float fDistance = fPriorSpeed - seg.m_fPercent; + float fRatioNeed = fRatioUsed * -fDistance; + return (fPriorSpeed + fRatioNeed); + } + else + { + return seg.m_fPercent; + } + +} + /* For visibility testing: if bAbsolute is false, random modifiers must return * the minimum possible scroll speed. */ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, float &fPeakYOffsetOut, bool &bIsPastPeakOut, bool bAbsolute ) @@ -233,7 +273,8 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float { float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; - fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); + float fSpeedMultiplier = GAMESTATE->m_bInStepEditor ? 1.0 : GetSpeedMultiplier( position.m_fSongBeatVisible, position.m_fMusicSecondsVisible, pCurSteps->m_Timing ); + fYOffset += fSpeedMultiplier * fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); } if( pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing != 0.0f ) @@ -251,42 +292,6 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float // (per issue 24), edit this to reflect that. -aj fYOffset *= ARROW_SPACING; - // Factor in the SpeedSegment. - TimingData &tim = pCurSteps->m_Timing; - - const int index = tim.GetSpeedSegmentIndexAtBeat( fSongBeat ); - if( !GAMESTATE->m_bInStepEditor && index > 0 ) - { - SpeedSegment &seg = tim.GetSpeedSegmentAtBeat( fSongBeat ); - float fStartBeat = NoteRowToBeat(seg.m_iStartRow); - float fStartTime = tim.GetElapsedTimeFromBeat( fStartBeat ); - float fEndTime; - - if( seg.m_usMode == 1 ) // seconds - { - fEndTime = fStartTime + seg.m_fWait; - } - else - { - fEndTime = tim.GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ); - } - float fCurTime = tim.GetElapsedTimeFromBeat( fSongBeat ); - - if( fEndTime >= fCurTime ) - { - const float fPriorSpeed = tim.m_SpeedSegments[index - 1].m_fPercent; - float fTimeUsed = fCurTime - fStartTime; - float fRatioUsed = fTimeUsed / (fEndTime - fStartTime); - - float fDistance = fPriorSpeed - seg.m_fPercent; - float fRatioNeed = fRatioUsed * -fDistance; - fYOffset *= (fPriorSpeed + fRatioNeed); - } - else - { - fYOffset *= seg.m_fPercent; - } - } // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) return fYOffset * pPlayerState->m_PlayerOptions.GetCurrent().m_fScrollSpeed; diff --git a/src/GameState.cpp b/src/GameState.cpp index 3b4f792986..76bd07acd5 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -128,7 +128,8 @@ GameState::GameState() : m_stEditSource( Message_EditSourceStepsTypeChanged ), m_iEditCourseEntryIndex( Message_EditCourseEntryIndexChanged ), m_sEditLocalProfileID( Message_EditLocalProfileIDChanged ), - m_bIsEditorStepTiming( true ) + m_bIsEditorStepTiming( true ), + m_bInStepEditor( false ) { g_pImpl = new GameStateImpl; From 0904892202904ebe5ab4903d9191d8c75efb10b4 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 12:32:23 +0700 Subject: [PATCH 238/333] [splittiming] make setting beat0offset in ScreenEdit's edit timing data menu work. --- src/ScreenEdit.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0851795b87..698ba15c05 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3133,11 +3133,7 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; - if( GAMESTATE->m_bIsEditorStepTiming ) - { - timing = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing; - } + TimingData &timing = GAMESTATE->m_bIsEditorStepTiming ? GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSong->m_SongTiming; timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } From 60133353c11b33392d7fd5bcbdb9290ac5cb7d35 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 02:00:17 -0400 Subject: [PATCH 239/333] [splittiming] Time for FakeSegments. No, these won't replace Fake Notes. --- Docs/Luadoc/Lua.xml | 1 + Docs/Luadoc/LuaDocumentation.xml | 3 + src/TimingData.cpp | 134 +++++++++++++++++++++++ src/TimingData.h | 182 +++++++++++++++++++++++++++++++ 4 files changed, 320 insertions(+) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index dfb4c7cce3..6aa9eda455 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1406,6 +1406,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index df9f17081b..1e519bf91c 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -3519,6 +3519,9 @@ Returns true if the TimingData contains warps. + + Returns true if the TimingData contains fake segments. + Returns true if the TimingData contains speed scrolling changes. diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 3fc509fab4..e4f0375e39 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -73,6 +73,11 @@ void TimingData::AddSpeedSegment( const SpeedSegment &seg ) m_SpeedSegments.insert( upper_bound(m_SpeedSegments.begin(), m_SpeedSegments.end(), seg), seg ); } +void TimingData::AddFakeSegment( const FakeSegment &seg ) +{ + m_FakeSegments.insert( upper_bound(m_FakeSegments.begin(), m_FakeSegments.end(), seg), seg ); +} + /* Change an existing BPM segment, merge identical segments together or insert a new one. */ void TimingData::SetBPMAtRow( int iNoteRow, float fBPM ) { @@ -288,6 +293,31 @@ void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait, unsigned } } +void TimingData::SetFakeAtRow( int iRow, float fNew ) +{ + unsigned i; + for( i=0; i 0 && NoteRowToBeat(iRow) < fNew; + if( i == m_FakeSegments.size() ) + { + if( valid ) + { + AddFakeSegment( FakeSegment(iRow, fNew) ); + } + } + else + { + if( valid ) + { + m_FakeSegments[i].m_fEndBeat = fNew; + } + else + m_FakeSegments.erase( m_FakeSegments.begin()+i, m_FakeSegments.begin()+i+1 ); + } +} + void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent ) { SetSpeedAtRow( iRow, @@ -373,6 +403,18 @@ unsigned short TimingData::GetSpeedModeAtRow( int iRow ) return GetSpeedSegmentAtRow( iRow ).m_usMode; } +float TimingData::GetFakeAtRow( int iFakeRow ) const +{ + for( unsigned i=0; i(i); } +int TimingData::GetFakeSegmentIndexAtRow( int iNoteRow ) const +{ + unsigned i; + for( i=0; i iNoteRow ) + break; + } + return static_cast(i); +} + bool TimingData::IsWarpAtRow( int iNoteRow ) const { if( m_WarpSegments.empty() ) @@ -477,6 +531,20 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const return false; } +bool TimingData::IsFakeAtRow( int iNoteRow ) const +{ + if( m_FakeSegments.empty() ) + return false; + + int i = GetFakeSegmentIndexAtRow( iNoteRow ); + const FakeSegment& s = m_FakeSegments[i]; + if( s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat) ) + { + return true; + } + return false; +} + int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const { unsigned i; @@ -595,6 +663,16 @@ WarpSegment& TimingData::GetWarpSegmentAtRow( int iRow ) return m_WarpSegments[i]; } +FakeSegment& TimingData::GetFakeSegmentAtRow( int iRow ) +{ + static FakeSegment empty; + if( m_FakeSegments.empty() ) + return empty; + + int i = GetFakeSegmentIndexAtRow( iRow ); + return m_FakeSegments[i]; +} + int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const { unsigned i; @@ -952,6 +1030,25 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool m_SpeedSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; } + for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) + { + const int iSegStartRow = m_FakeSegments[i].m_iStartRow; + const int iSegEndRow = BeatToNoteRow( m_FakeSegments[i].m_fEndBeat ); + if( iSegEndRow >= iStartIndex ) + { + if( iSegEndRow > iEndIndex ) + m_FakeSegments[i].m_fEndBeat += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + else + m_FakeSegments[i].m_fEndBeat = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale) + iStartIndex); + } + if( iSegStartRow < iStartIndex ) + continue; + else if( iSegStartRow > iEndIndex ) + m_FakeSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + else + m_FakeSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + } + // adjust BPM changes to preserve timing if( bAdjustBPM ) { @@ -1044,6 +1141,16 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) continue; sped.m_iStartRow += iRowsToAdd; } + + for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) + { + FakeSegment &fake = m_FakeSegments[i]; + if( BeatToNoteRow(fake.m_fEndBeat) >= iStartRow ) + fake.m_fEndBeat += NoteRowToBeat(iRowsToAdd); + if( fake.m_iStartRow < iStartRow ) + continue; + fake.m_iStartRow += iRowsToAdd; + } if( iStartRow == 0 ) { @@ -1217,6 +1324,26 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } sped.m_iStartRow -= iRowsToDelete; } + + for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) + { + FakeSegment &fake = m_FakeSegments[i]; + + if( BeatToNoteRow(fake.m_fEndBeat) >= iStartRow ) + fake.m_fEndBeat = max( NoteRowToBeat(iStartRow), fake.m_fEndBeat - NoteRowToBeat(iRowsToDelete) ); + + if( fake.m_iStartRow < iStartRow ) + continue; + + if( fake.m_iStartRow < iStartRow+iRowsToDelete ) + { + m_FakeSegments.erase( m_FakeSegments.begin()+i, m_FakeSegments.begin()+i+1 ); + --i; + continue; + } + + fake.m_iStartRow -= iRowsToDelete; + } this->SetBPMAtRow( iStartRow, fNewBPM ); } @@ -1292,6 +1419,11 @@ bool TimingData::HasWarps() const return m_WarpSegments.size()>0; } +bool TimingData::HasFakes() const +{ + return m_FakeSegments.size()>0; +} + bool TimingData::HasSpeedChanges() const { return m_SpeedSegments.size()>1; @@ -1343,6 +1475,7 @@ public: static int HasStops( T* p, lua_State *L ) { lua_pushboolean(L, p->HasStops()); return 1; } static int HasBPMChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasBpmChanges()); return 1; } static int HasWarps( T* p, lua_State *L ) { lua_pushboolean(L, p->HasWarps()); return 1; } + static int HasFakes( T* p, lua_State *L ) { lua_pushboolean(L, p->HasFakes()); return 1; } static int HasSpeedChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasSpeedChanges()); return 1; } static int GetStops( T* p, lua_State *L ) { @@ -1431,6 +1564,7 @@ public: ADD_METHOD( HasStops ); ADD_METHOD( HasBPMChanges ); ADD_METHOD( HasWarps ); + ADD_METHOD( HasFakes ); ADD_METHOD( HasSpeedChanges ); ADD_METHOD( GetStops ); ADD_METHOD( GetDelays ); diff --git a/src/TimingData.h b/src/TimingData.h index b24cccdc5a..61ee14cd16 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -777,6 +777,113 @@ struct SpeedSegment bool operator>=( const SpeedSegment &other ) const { return !operator<(other); } }; +/** + * @brief Identifies when a whole region of arrows is to be ignored. + * + * FakeSegments are similar to the Fake Tap Notes in that the contents + * inside are neither for nor against the player. They can be useful for + * mission modes, in conjunction with WarpSegments, or perhaps other + * uses not thought up at the time of this comment. Unlike the Warp + * Segments, these are not magically jumped over: instead, these are + * drawn normally. + * + * These were inspired by the Pump It Up series. */ +struct FakeSegment +{ + /** + * @brief Create a simple Fake Segment with default values. + * + * It is best to override the values as soon as possible. + */ + FakeSegment() : m_iStartRow(-1), m_fEndBeat(-1) { } + /** + * @brief Create a Fake Segment with the specified values. + * @param s the starting row of this segment. + * @param r the row to be real again. + */ + FakeSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), + m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} + /** + * @brief Creates a Fake Segment with the specified values. + * @param s the starting row of this segment. + * @param b the beat to be real again. + */ + FakeSegment( int s, float b ): m_iStartRow(max(0, s)), + m_fEndBeat(max(0, b)) {} + /** + * @brief Create a Fake Segment with the specified values. + * @param s the starting beat in this segment. + * @param r the row to be real again. + */ + FakeSegment( float s, int r ): + m_iStartRow(max(0, BeatToNoteRow(s))), + m_fEndBeat(max(0, NoteRowToBeat(r))) {} + /** + * @brief Creates a Fake Segment with the specified values. + * @param s the starting beat of this segment. + * @param b the beat to be real again. + */ + FakeSegment( float s, float b ): + m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), + m_fEndBeat(max(0, (b > s ? b : s))) {} + /** + * @brief The row in which the FakeSegment activates. + */ + int m_iStartRow; + /** + * @brief The beat that ends the FakeSegment. + */ + float m_fEndBeat; + /** + * @brief Compares two FakeSegments to see if they are equal to each other. + * @param other the other FakeSegment to compare to. + * @return the equality of the two segments. + */ + bool operator==( const FakeSegment &other ) const + { + COMPARE( m_iStartRow ); + COMPARE( m_fEndBeat ); + return true; + } + /** + * @brief Compares two FakeSegments to see if they are not equal to each other. + * @param other the other FakeSegment to compare to. + * @return the inequality of the two segments. + */ + bool operator!=( const FakeSegment &other ) const { return !operator==(other); } + /** + * @brief Compares two FakeSegments to see if one is less than the other. + * @param other the other FakeSegment to compare to. + * @return the truth/falsehood of if the first is less than the second. + */ + bool operator<( const FakeSegment &other ) const + { + return m_iStartRow < other.m_iStartRow || + ( m_iStartRow == other.m_iStartRow && m_fEndBeat < other.m_fEndBeat ); + } + /** + * @brief Compares two FakeSegments to see if one is less than or equal to the other. + * @param other the other FakeSegment to compare to. + * @return the truth/falsehood of if the first is less or equal to than the second. + */ + bool operator<=( const FakeSegment &other ) const + { + return ( operator<(other) || operator==(other) ); + } + /** + * @brief Compares two FakeSegments to see if one is greater than the other. + * @param other the other FakeSegment to compare to. + * @return the truth/falsehood of if the first is greater than the second. + */ + bool operator>( const FakeSegment &other ) const { return !operator<=(other); } + /** + * @brief Compares two FakeSegments to see if one is greater than or equal to the other. + * @param other the other FakeSegment to compare to. + * @return the truth/falsehood of if the first is greater than or equal to the second. + */ + bool operator>=( const FakeSegment &other ) const { return !operator<(other); } +}; + /** * @brief Holds data for translating beats<->seconds. @@ -1487,6 +1594,72 @@ public: */ void AddSpeedSegment( const SpeedSegment &seg ); + /** + * @brief Determine when the fakes end. + * @param iRow The row you start on. + * @return the time when the fakes end. + */ + float GetFakeAtRow( int iRow ) const; + /** + * @brief Determine when the fakes end. + * @param fBeat The beat you start on. + * @return the time when the fakes end. + */ + float GetFakeAtBeat( float fBeat ) const { return GetFakeAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Set the beat to indicate when the FakeSegment ends. + * @param iRow The row to start on. + * @param fNew The destination beat. + */ + void SetFakeAtRow( int iRow, float fNew ); + /** + * @brief Set the beat to indicate when the FakeSegment ends. + * @param fBeat The beat to start on. + * @param fNew The destination beat. + */ + void SetFakeAtBeat( float fBeat, float fNew ) { SetFakeAtRow( BeatToNoteRow( fBeat ), fNew ); } + /** + * @brief Retrieve the FakeSegment at the specified row. + * @param iRow the row to focus on. + * @return the FakeSegment in question. + */ + FakeSegment& GetFakeSegmentAtRow( int iRow ); + /** + * @brief Retrieve the FakeSegment at the specified beat. + * @param fBeat the beat to focus on. + * @return the FakeSegment in question. + */ + FakeSegment& GetFakeSegmentAtBeat( float fBeat ) { return GetFakeSegmentAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Retrieve the index of the FakeSegment at the specified row. + * @param iRow the row to focus on. + * @return the index in question. + */ + int GetFakeSegmentIndexAtRow( int iRow ) const; + /** + * @brief Retrieve the index of the FakeSegment at the specified beat. + * @param fBeat the beat to focus on. + * @return the index in question. + */ + int GetFakeSegmentIndexAtBeat( float fBeat ) const { return GetFakeSegmentIndexAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Checks if the row is inside a fake. + * @param iRow the row to focus on. + * @return true if the row is inside a fake, false otherwise. + */ + bool IsFakeAtRow( int iRow ) const; + /** + * @brief Checks if the beat is inside a fake. + * @param fBeat the beat to focus on. + * @return true if the row is inside a fake, false otherwise. + */ + bool IsFakeAtBeat( float fBeat ) const { return IsFakeAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Add the FakeSegment to the TimingData. + * @param seg the new FakeSegment. + */ + void AddFakeSegment( const FakeSegment &seg ); + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); @@ -1531,6 +1704,10 @@ public: * @return true if there is at least one warp, false otherwise. */ bool HasWarps() const; + /** + * @brief View the TimingData to see if there is at least one fake segment involved. + * @return true if there is at least one fake segment, false otherwise. */ + bool HasFakes() const; /** * @brief View the TimingData to see if a song changes its speed scrolling at any point. * @return true if there is at least one change, false otherwise. */ @@ -1566,6 +1743,9 @@ public: COMPARE( m_SpeedSegments.size() ); for( unsigned i=0; i m_LabelSegments; /** @brief The collection of SpeedSegments. */ vector m_SpeedSegments; + /** @brief The collection of FakeSegments. */ + vector m_FakeSegments; /** * @brief The initial offset of a song. */ From 49552d41e5fb3ce3b872c7cdffe0172beca47b52 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 09:41:07 -0400 Subject: [PATCH 240/333] [splittiming] Don't need this pre-filled. --- src/ScreenEdit.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 698ba15c05..95e51299b0 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -4002,13 +4002,11 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice break; case speed_mode: { - RString sMode = ( GetAppropriateTiming().GetSpeedModeAtBeat( GetBeat() ) == 0 ? - "Beats" : "Seconds" ); ScreenTextEntry::TextEntry( SM_BackFromSpeedModeChange, ENTER_SPEED_MODE_VALUE, - sMode.c_str(), - 10 + "", + 3 ); break; From ba8791b4f990d0d3cf552d7d98b6405cd3011e23 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 09:44:07 -0400 Subject: [PATCH 241/333] [splittiming] Only care about the mod change. Nothing wrong with the rest, but for editor purposes, this kind of takes precedence before length and unit. --- src/TimingData.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index e4f0375e39..dcc6b3e560 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -271,17 +271,14 @@ void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait, unsigned if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].m_iStartRow != iRow ) { - if( i == 0 || - ( m_SpeedSegments[i-1].m_fPercent != fPercent - || m_SpeedSegments[i-1].m_fWait != fWait - || m_SpeedSegments[i-1].m_usMode != usMode ) ) + // the core mod itself matters the most for comparisons. + if( i == 0 || m_SpeedSegments[i-1].m_fPercent != fPercent ) AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait, usMode) ); } else { - if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent - && m_SpeedSegments[i-1].m_fWait == fWait - && m_SpeedSegments[i-1].m_usMode == usMode ) + // The others aren't compared: only the mod itself matters. + if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent ) m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); else From 329798e0d612c323c2e78dca96ec6911c6aed311 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:02:57 -0400 Subject: [PATCH 242/333] [splittiming] Few things with NotesLoader/Writer: 1) Start to accept FakeSegments. 2) Start the transition to relative points for Warps. 3) Again, song timings don't get FakeSegments. --- src/NotesLoaderSMA.cpp | 36 +++++++++++++++++++++++ src/NotesLoaderSMA.h | 1 + src/NotesLoaderSSC.cpp | 67 +++++++++++++++++++++++++++++++++++++----- src/NotesLoaderSSC.h | 3 +- src/NotesWriterSSC.cpp | 8 ++++- 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 23dd584691..de181db967 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -355,6 +355,35 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS } } +void SMALoader::ProcessFakes( TimingData &out, const int iRowsPerBeat, const RString sParam ) +{ + vector arrayFakeExpressions; + split( sParam, ",", arrayFakeExpressions ); + + for( unsigned b=0; b arrayFakeValues; + split( arrayFakeExpressions[b], "=", arrayFakeValues ); + // XXX: Hard to tell which file caused this. + if( arrayFakeValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #FAKES value \"%s\" (must have exactly one '='), ignored.", + arrayFakeExpressions[b].c_str() ); + continue; + } + + const float fBeat = RowToBeat( arrayFakeValues[0], iRowsPerBeat ); + const float fNewBeat = StringToFloat( arrayFakeValues[1] ); + + if(fNewBeat > 0) + out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) ); + else + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Fake at beat %f, BPM %f.", fBeat, fNewBeat ); + } + } +} + void SMALoader::LoadFromSMATokens( RString sStepsType, @@ -685,6 +714,13 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) ProcessMultipliers( pNewNotes->m_Timing, iRowsPerBeat, sParams[1] ); } + else if( sValueName=="FAKES" ) + { + TimingData &timing = (state == SMA_GETTING_STEP_INFO + ? pNewNotes->m_Timing : out.m_SongTiming); + ProcessFakes( timing, iRowsPerBeat, sParams[1] ); + } + else if( sValueName=="METERTYPE" ) { ; // We don't use this...yet. diff --git a/src/NotesLoaderSMA.h b/src/NotesLoaderSMA.h index af397205fb..c9e3dfa811 100644 --- a/src/NotesLoaderSMA.h +++ b/src/NotesLoaderSMA.h @@ -48,6 +48,7 @@ namespace SMALoader void ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam ); void ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam ); + void ProcessFakes( TimingData &out, const int iRowsPerBeat, const RString sParam ); float RowToBeat( RString sLine, const int iRowsPerBeat ); }; diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 352387e7df..b361629db0 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -46,7 +46,7 @@ bool SSCLoader::LoadFromDir( const RString &sPath, Song &out ) return LoadFromSSCFile( sPath + aFileNames[0], out ); } -void SSCLoader::ProcessWarps( TimingData &out, const RString sParam ) +void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float fVersion ) { vector arrayWarpExpressions; split( sParam, ",", arrayWarpExpressions ); @@ -65,8 +65,8 @@ void SSCLoader::ProcessWarps( TimingData &out, const RString sParam ) const float fBeat = StringToFloat( arrayWarpValues[0] ); const float fNewBeat = StringToFloat( arrayWarpValues[1] ); - - if(fNewBeat > fBeat) + // Early versions were absolute in beats. They should be relative. + if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) || fNewBeat > 0 ) out.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); else { @@ -172,6 +172,35 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) } } +void SSCLoader::ProcessFakes( TimingData &out, const RString sParam ) +{ + vector arrayFakeExpressions; + split( sParam, ",", arrayFakeExpressions ); + + for( unsigned b=0; b arrayFakeValues; + split( arrayFakeExpressions[b], "=", arrayFakeValues ); + // XXX: Hard to tell which file caused this. + if( arrayFakeValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #FAKES value \"%s\" (must have exactly one '='), ignored.", + arrayFakeExpressions[b].c_str() ); + continue; + } + + const float fBeat = StringToFloat( arrayFakeValues[0] ); + const float fNewBeat = StringToFloat( arrayFakeValues[1] ); + + if(fNewBeat > 0) + out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) ); + else + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Fake at beat %f, BPM %f.", fBeat, fNewBeat ); + } + } +} + bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache ) { @@ -393,9 +422,9 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach SMLoader::ProcessBPMs(out.m_SongTiming, sParams[1]); } - else if( sValueName=="WARPS" ) + else if( sValueName=="WARPS" ) // Older versions allowed em here. { - ProcessWarps( out.m_SongTiming, sParams[1] ); + ProcessWarps( out.m_SongTiming, sParams[1], out.m_fVersion ); } else if( sValueName=="LABELS" ) @@ -560,7 +589,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="WARPS" ) { - ProcessWarps(stepsTiming, sParams[1]); + ProcessWarps(stepsTiming, sParams[1], out.m_fVersion); } else if( sValueName=="SPEEDS" ) @@ -568,6 +597,11 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach ProcessSpeeds( stepsTiming, sParams[1] ); } + else if( sValueName=="FAKES" ) + { + ProcessFakes( stepsTiming, sParams[1] ); + } + else if( sValueName=="LABELS" ) { ProcessLabels(stepsTiming, sParams[1]); @@ -675,7 +709,12 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat sValueName.MakeUpper(); // handle the data - if( sValueName=="SONG" ) + if( sValueName=="VERSION" ) + { + pSong->m_fVersion = StringToFloat( sParams[1] ); + } + + else if( sValueName=="SONG" ) { if( pSong ) { @@ -795,7 +834,19 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat else if( sValueName=="WARPS" ) { - ProcessWarps(stepsTiming, sParams[1]); + ProcessWarps(stepsTiming, sParams[1], pSong->m_fVersion); + bSSCFormat = true; + } + + else if( sValueName=="SPEEDS" ) + { + ProcessSpeeds( stepsTiming, sParams[1] ); + bSSCFormat = true; + } + + else if( sValueName=="FAKES" ) + { + ProcessFakes( stepsTiming, sParams[1] ); bSSCFormat = true; } diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index c78231677b..cccf26c45f 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -77,10 +77,11 @@ namespace SSCLoader void TidyUpData( Song &song, bool bFromCache ); - void ProcessWarps( TimingData &, const RString ); + void ProcessWarps( TimingData &, const RString, const float ); void ProcessLabels( TimingData &, const RString ); void ProcessCombos( TimingData &, const RString ); void ProcessSpeeds( TimingData &, const RString ); + void ProcessFakes( TimingData &, const RString ); } #endif /** diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3b7c4ae729..3f01843b06 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -140,6 +140,11 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode ); w.Finish(); + + w.Init( "FAKES" ); + FOREACH_CONST( FakeSegment, timing.m_FakeSegments, fs ) + w.Write( fs->m_iStartRow, fs->m_fEndBeat ); + w.Finish(); } w.Init( "LABELS" ); @@ -312,7 +317,8 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa GetTimingTags( lines, in.m_Timing ); - lines.push_back( "#ATTACKS:;" ); // not sure of how to handle this yet. + // For now, attacks are NOT in use for the step. + lines.push_back( "#ATTACKS:;" ); lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) ); RString sNoteData; From b12adc82e183d90114f11bbd54f874005e470693 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:05:56 -0400 Subject: [PATCH 243/333] [splittiming] Simplify. --- src/NotesLoaderSMA.cpp | 56 +++--------------------------------------- src/NotesLoaderSSC.cpp | 45 +-------------------------------- 2 files changed, 4 insertions(+), 97 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index de181db967..58ced62bd6 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -395,59 +395,9 @@ void SMALoader::LoadFromSMATokens( Steps &out ) { - // we're loading from disk, so this is by definition already saved: - out.SetSavedToDisk( true ); - - Trim( sStepsType ); - Trim( sDescription ); - Trim( sDifficulty ); - Trim( sNoteData ); - - // LOG->Trace( "Steps::LoadFromSMTokens()" ); - - // insert stepstype hacks from GameManager.cpp here? -aj - out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType ); - out.SetDescription( sDescription ); - out.SetCredit( sDescription ); // this is often used for both. - out.SetDifficulty( StringToDifficulty(sDifficulty) ); - - sDescription.MakeLower(); - - // Handle hacks that originated back when StepMania didn't have - // Difficulty_Challenge. (At least v1.64, possibly v3.0 final...) - if( out.GetDifficulty() == Difficulty_Hard ) - { - // HACK: SMANIAC used to be Difficulty_Hard with a special description. - if( sDescription == "smaniac" ) - out.SetDifficulty( Difficulty_Challenge ); - - // HACK: CHALLENGE used to be Difficulty_Hard with a special description. - if( sDescription == "challenge" ) - out.SetDifficulty( Difficulty_Challenge ); - } - - out.SetMeter( StringToInt(sMeter) ); - vector saValues; - split( sRadarValues, ",", saValues, true ); - int categories = NUM_RadarCategory - 1; // Fakes aren't counted in the radar values. - if( saValues.size() == (unsigned)categories * NUM_PLAYERS ) - { - RadarValues v[NUM_PLAYERS]; - FOREACH_PlayerNumber( pn ) - { - // Can't use the foreach anymore due to flexible radar lines. - for( RadarCategory rc = (RadarCategory)0; rc < categories; - enum_add( rc, 1 ) ) - { - v[pn][rc] = StringToFloat( saValues[pn*categories + rc] ); - } - } - out.SetCachedRadarValues( v ); - } - - out.SetSMNoteData( sNoteData ); - - out.TidyUpData(); + SMLoader::LoadFromSMATokens( sStepsType, sDescription, + sDifficulty, sMeter, sRadarValues, + sNoteData, out ); } void SMALoader::TidyUpData( Song &song, bool bFromCache ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index b361629db0..5019bf9ec0 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -609,50 +609,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="ATTACKS" ) { - // TODO: Look into Step attacks vs Song Attacks. -Wolfman2000 - /* - // Build the RString vector here so we can write it to file again later - for( unsigned s=1; s < sParams.params.size(); ++s ) - out.m_sAttackString.push_back( sParams[s] ); - - Attack attack; - float end = -9999; - - for( unsigned j=1; j < sParams.params.size(); ++j ) - { - vector sBits; - split( sParams[j], "=", sBits, false ); - - // Need an identifer and a value for this to work - if( sBits.size() < 2 ) - continue; - - TrimLeft( sBits[0] ); - TrimRight( sBits[0] ); - - if( !sBits[0].CompareNoCase("TIME") ) - attack.fStartSecond = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("LEN") ) - attack.fSecsRemaining = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("END") ) - end = strtof( sBits[1], NULL ); - else if( !sBits[0].CompareNoCase("MODS") ) - { - attack.sModifiers = sBits[1]; - - if( end != -9999 ) - { - attack.fSecsRemaining = end - attack.fStartSecond; - end = -9999; - } - - if( attack.fSecsRemaining < 0.0f ) - attack.fSecsRemaining = 0.0f; - - out.m_Attacks.push_back( attack ); - } - } - */ + // Step Attacks aren't in yet. } else if( sValueName=="OFFSET" ) From 79135b3179300e0ca4bdab44327cde117203d86e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:16:24 -0400 Subject: [PATCH 244/333] [splittiming] Oops. --- src/NotesLoaderSMA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 58ced62bd6..ca2ff66c84 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -395,7 +395,7 @@ void SMALoader::LoadFromSMATokens( Steps &out ) { - SMLoader::LoadFromSMATokens( sStepsType, sDescription, + SMLoader::LoadFromSMTokens( sStepsType, sDescription, sDifficulty, sMeter, sRadarValues, sNoteData, out ); } From b3c16e3dee4c7474a3e4edce86dc36c0972f0ea6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:24:59 -0400 Subject: [PATCH 245/333] [splittiming] Warps and Fakes are relative timed. theDtTvB, time to scrutinize my work. ;) --- src/TimingData.cpp | 50 +++++++++++++++++++++------------------------- src/TimingData.h | 24 +++++++++++----------- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index dcc6b3e560..6c3adbd267 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -176,7 +176,7 @@ void TimingData::SetWarpAtRow( int iRow, float fNew ) for( i=0; i 0 && NoteRowToBeat(iRow) < fNew; + bool valid = iRow > 0 && fNew > 0; if( i == m_WarpSegments.size() ) { if( valid ) @@ -513,7 +513,7 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const int i = GetWarpSegmentIndexAtRow( iNoteRow ); const WarpSegment& s = m_WarpSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat) ) + if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fEndBeat) ) ) { if( m_StopSegments.empty() ) { @@ -535,7 +535,7 @@ bool TimingData::IsFakeAtRow( int iNoteRow ) const int i = GetFakeSegmentIndexAtRow( iNoteRow ); const FakeSegment& s = m_FakeSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat) ) + if( s.m_iStartRow <= iNoteRow && iNoteRow < ( s.m_iStartRow + BeatToNoteRow(s.m_fEndBeat) ) ) { return true; } @@ -829,15 +829,18 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float } break; case FOUND_WARP: - bIsWarping = true; - if( itWS->m_fEndBeat > fWarpDestination ) { - fWarpDestination = itWS->m_fEndBeat; + bIsWarping = true; + float fWarpSum = itWS->m_fEndBeat + NoteRowToBeat( itWS->m_iStartRow ); + if( fWarpSum > fWarpDestination ) + { + fWarpDestination = itWS->m_fEndBeat; + } + iWarpBeginOut = iEventRow; + fWarpDestinationOut = fWarpDestination; + itWS ++; + break; } - iWarpBeginOut = iEventRow; - fWarpDestinationOut = fWarpDestination; - itWS ++; - break; } iLastRow = iEventRow; } @@ -921,13 +924,16 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const case FOUND_MARKER: return fLastTime; case FOUND_WARP: - bIsWarping = true; - if( itWS->m_fEndBeat > fWarpDestination ) { - fWarpDestination = itWS->m_fEndBeat; + bIsWarping = true; + float fWarpSum = itWS->m_fEndBeat + NoteRowToBeat( itWS->m_iStartRow ); + if( fWarpSum > fWarpDestination ) + { + fWarpDestination = itWS->m_fEndBeat; + } + itWS ++; + break; } - itWS ++; - break; } iLastRow = iEventRow; } @@ -967,7 +973,7 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { const int iSegStartRow = m_WarpSegments[i].m_iStartRow; - const int iSegEndRow = BeatToNoteRow( m_WarpSegments[i].m_fEndBeat ); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_WarpSegments[i].m_fEndBeat ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) @@ -1030,7 +1036,7 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { const int iSegStartRow = m_FakeSegments[i].m_iStartRow; - const int iSegEndRow = BeatToNoteRow( m_FakeSegments[i].m_fEndBeat ); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_FakeSegments[i].m_fEndBeat ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) @@ -1093,8 +1099,6 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { WarpSegment &warp = m_WarpSegments[i]; - if( BeatToNoteRow(warp.m_fEndBeat) >= iStartRow ) - warp.m_fEndBeat += NoteRowToBeat(iRowsToAdd); if( warp.m_iStartRow < iStartRow ) continue; warp.m_iStartRow += iRowsToAdd; @@ -1142,8 +1146,6 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { FakeSegment &fake = m_FakeSegments[i]; - if( BeatToNoteRow(fake.m_fEndBeat) >= iStartRow ) - fake.m_fEndBeat += NoteRowToBeat(iRowsToAdd); if( fake.m_iStartRow < iStartRow ) continue; fake.m_iStartRow += iRowsToAdd; @@ -1210,9 +1212,6 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) { WarpSegment &warp = m_WarpSegments[i]; - if( BeatToNoteRow(warp.m_fEndBeat) >= iStartRow ) - warp.m_fEndBeat = max( NoteRowToBeat(iStartRow), warp.m_fEndBeat - NoteRowToBeat(iRowsToDelete) ); - if( warp.m_iStartRow < iStartRow ) continue; @@ -1326,9 +1325,6 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) { FakeSegment &fake = m_FakeSegments[i]; - if( BeatToNoteRow(fake.m_fEndBeat) >= iStartRow ) - fake.m_fEndBeat = max( NoteRowToBeat(iStartRow), fake.m_fEndBeat - NoteRowToBeat(iRowsToDelete) ); - if( fake.m_iStartRow < iStartRow ) continue; diff --git a/src/TimingData.h b/src/TimingData.h index 61ee14cd16..655a39a2a7 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -313,8 +313,8 @@ struct TimeSignatureSegment * * A warp segment is used to replicate the effects of Negative BPMs without * abusing negative BPMs. Negative BPMs should be converted to warp segments. - * WarpAt=WarpTo is the format, where both are in beats. (Technically they're - * both rows though.) */ + * WarpAt=WarpToRelative is the format, where both are in beats. + * (Technically they're both rows though.) */ struct WarpSegment { /** @@ -326,21 +326,21 @@ struct WarpSegment /** * @brief Create a Warp Segment with the specified starting row and row to warp to. * @param s the starting row of this segment. - * @param r the row to warp to. + * @param r the number of rows to jump ahead. */ WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Warp Segment with the specified starting row and beat to warp to. * @param s the starting row of this segment. - * @param b the beat to warp to. + * @param b the number of beats to jump ahead. */ WarpSegment( int s, float b ): m_iStartRow(max(0, s)), m_fEndBeat(max(0, b)) {} /** * @brief Create a Warp Segment with the specified starting beat and row to warp to. * @param s the starting beat in this segment. - * @param r the row to warp to. + * @param r the number of rows to jump ahead. */ WarpSegment( float s, int r ): m_iStartRow(max(0, BeatToNoteRow(s))), @@ -348,7 +348,7 @@ struct WarpSegment /** * @brief Creates a Warp Segment with the specified starting beat and beat to warp to. * @param s the starting beat of this segment. - * @param b the beat to warp to. + * @param b the number of beats to jump ahead. */ WarpSegment( float s, float b ): m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), @@ -358,7 +358,7 @@ struct WarpSegment */ int m_iStartRow; /** - * @brief The beat to warp to. + * @brief The number of beats to warp ahead by. */ float m_fEndBeat; /** @@ -799,21 +799,21 @@ struct FakeSegment /** * @brief Create a Fake Segment with the specified values. * @param s the starting row of this segment. - * @param r the row to be real again. + * @param r the number of rows this segment lasts. */ FakeSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Fake Segment with the specified values. * @param s the starting row of this segment. - * @param b the beat to be real again. + * @param b the number of beats this segment lasts. */ FakeSegment( int s, float b ): m_iStartRow(max(0, s)), m_fEndBeat(max(0, b)) {} /** * @brief Create a Fake Segment with the specified values. * @param s the starting beat in this segment. - * @param r the row to be real again. + * @param r the number of rows this segment lasts. */ FakeSegment( float s, int r ): m_iStartRow(max(0, BeatToNoteRow(s))), @@ -821,7 +821,7 @@ struct FakeSegment /** * @brief Creates a Fake Segment with the specified values. * @param s the starting beat of this segment. - * @param b the beat to be real again. + * @param b the number of beats this segment lasts. */ FakeSegment( float s, float b ): m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), @@ -831,7 +831,7 @@ struct FakeSegment */ int m_iStartRow; /** - * @brief The beat that ends the FakeSegment. + * @brief The number of beats the FakeSegment is alive for. */ float m_fEndBeat; /** From ea21b98826dd62c4adf0be0356e837282803be83 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:45:03 -0400 Subject: [PATCH 246/333] [splittiming] Version fix. --- src/NotesLoaderSSC.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 5019bf9ec0..5e7a9bcc68 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -66,7 +66,11 @@ void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float const float fBeat = StringToFloat( arrayWarpValues[0] ); const float fNewBeat = StringToFloat( arrayWarpValues[1] ); // Early versions were absolute in beats. They should be relative. - if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) || fNewBeat > 0 ) + if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) ) + { + out.AddWarpSegment( WarpSegment(fBeat, fNewBeat - fBeat) ); + } + else if( fNewBeat > 0 ) out.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); else { From 1f7389a7a4a5534b9d2f66b700ca8cf515cc1b6a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:49:55 -0400 Subject: [PATCH 247/333] [splittiming] Don't do variable swapping. Next up: fixing the editor. --- src/TimingData.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/TimingData.h b/src/TimingData.h index 655a39a2a7..60ac6ae8a8 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -328,8 +328,8 @@ struct WarpSegment * @param s the starting row of this segment. * @param r the number of rows to jump ahead. */ - WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), - m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} + WarpSegment( int s, int r ): m_iStartRow(s), + m_fEndBeat(NoteRowToBeat(r)) {} /** * @brief Creates a Warp Segment with the specified starting row and beat to warp to. * @param s the starting row of this segment. @@ -351,8 +351,8 @@ struct WarpSegment * @param b the number of beats to jump ahead. */ WarpSegment( float s, float b ): - m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), - m_fEndBeat(max(0, (b > s ? b : s))) {} + m_iStartRow(BeatToNoteRow(s)), + m_fEndBeat(b) {} /** * @brief The row in which the WarpSegment activates. */ @@ -801,8 +801,8 @@ struct FakeSegment * @param s the starting row of this segment. * @param r the number of rows this segment lasts. */ - FakeSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), - m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} + FakeSegment( int s, int r ): m_iStartRow(s), + m_fEndBeat(NoteRowToBeat(r)) {} /** * @brief Creates a Fake Segment with the specified values. * @param s the starting row of this segment. @@ -824,8 +824,8 @@ struct FakeSegment * @param b the number of beats this segment lasts. */ FakeSegment( float s, float b ): - m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), - m_fEndBeat(max(0, (b > s ? b : s))) {} + m_iStartRow(BeatToNoteRow(s)), + m_fEndBeat(b) {} /** * @brief The row in which the FakeSegment activates. */ From b7dc61104803f786ef364dc3cd46f55cee1a1437 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 21:55:32 +0700 Subject: [PATCH 248/333] [splittiming] rename m_fEndBeat to m_fLengthBeats. let's see how many build errors we have. --- src/TimingData.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/TimingData.h b/src/TimingData.h index 655a39a2a7..a44f566041 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -322,21 +322,21 @@ struct WarpSegment * * It is best to override the values as soon as possible. */ - WarpSegment() : m_iStartRow(-1), m_fEndBeat(-1) { } + WarpSegment() : m_iStartRow(-1), m_fLengthBeats(-1) { } /** * @brief Create a Warp Segment with the specified starting row and row to warp to. * @param s the starting row of this segment. * @param r the number of rows to jump ahead. */ WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), - m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} + m_fLengthBeats(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Warp Segment with the specified starting row and beat to warp to. * @param s the starting row of this segment. * @param b the number of beats to jump ahead. */ WarpSegment( int s, float b ): m_iStartRow(max(0, s)), - m_fEndBeat(max(0, b)) {} + m_fLengthBeats(max(0, b)) {} /** * @brief Create a Warp Segment with the specified starting beat and row to warp to. * @param s the starting beat in this segment. @@ -344,7 +344,7 @@ struct WarpSegment */ WarpSegment( float s, int r ): m_iStartRow(max(0, BeatToNoteRow(s))), - m_fEndBeat(max(0, NoteRowToBeat(r))) {} + m_fLengthBeats(max(0, NoteRowToBeat(r))) {} /** * @brief Creates a Warp Segment with the specified starting beat and beat to warp to. * @param s the starting beat of this segment. @@ -352,7 +352,7 @@ struct WarpSegment */ WarpSegment( float s, float b ): m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), - m_fEndBeat(max(0, (b > s ? b : s))) {} + m_fLengthBeats(max(0, (b > s ? b : s))) {} /** * @brief The row in which the WarpSegment activates. */ @@ -360,7 +360,7 @@ struct WarpSegment /** * @brief The number of beats to warp ahead by. */ - float m_fEndBeat; + float m_fLengthBeats; /** * @brief Compares two WarpSegments to see if they are equal to each other. * @param other the other WarpSegment to compare to. @@ -369,7 +369,7 @@ struct WarpSegment bool operator==( const WarpSegment &other ) const { COMPARE( m_iStartRow ); - COMPARE( m_fEndBeat ); + COMPARE( m_fLengthBeats ); return true; } /** @@ -386,7 +386,7 @@ struct WarpSegment bool operator<( const WarpSegment &other ) const { return m_iStartRow < other.m_iStartRow || - ( m_iStartRow == other.m_iStartRow && m_fEndBeat < other.m_fEndBeat ); + ( m_iStartRow == other.m_iStartRow && m_fLengthBeats < other.m_fLengthBeats ); } /** * @brief Compares two WarpSegments to see if one is less than or equal to the other. @@ -795,21 +795,21 @@ struct FakeSegment * * It is best to override the values as soon as possible. */ - FakeSegment() : m_iStartRow(-1), m_fEndBeat(-1) { } + FakeSegment() : m_iStartRow(-1), m_fLengthBeats(-1) { } /** * @brief Create a Fake Segment with the specified values. * @param s the starting row of this segment. * @param r the number of rows this segment lasts. */ FakeSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), - m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} + m_fLengthBeats(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Fake Segment with the specified values. * @param s the starting row of this segment. * @param b the number of beats this segment lasts. */ FakeSegment( int s, float b ): m_iStartRow(max(0, s)), - m_fEndBeat(max(0, b)) {} + m_fLengthBeats(max(0, b)) {} /** * @brief Create a Fake Segment with the specified values. * @param s the starting beat in this segment. @@ -817,7 +817,7 @@ struct FakeSegment */ FakeSegment( float s, int r ): m_iStartRow(max(0, BeatToNoteRow(s))), - m_fEndBeat(max(0, NoteRowToBeat(r))) {} + m_fLengthBeats(max(0, NoteRowToBeat(r))) {} /** * @brief Creates a Fake Segment with the specified values. * @param s the starting beat of this segment. @@ -825,7 +825,7 @@ struct FakeSegment */ FakeSegment( float s, float b ): m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), - m_fEndBeat(max(0, (b > s ? b : s))) {} + m_fLengthBeats(max(0, (b > s ? b : s))) {} /** * @brief The row in which the FakeSegment activates. */ @@ -833,7 +833,7 @@ struct FakeSegment /** * @brief The number of beats the FakeSegment is alive for. */ - float m_fEndBeat; + float m_fLengthBeats; /** * @brief Compares two FakeSegments to see if they are equal to each other. * @param other the other FakeSegment to compare to. @@ -842,7 +842,7 @@ struct FakeSegment bool operator==( const FakeSegment &other ) const { COMPARE( m_iStartRow ); - COMPARE( m_fEndBeat ); + COMPARE( m_fLengthBeats ); return true; } /** @@ -859,7 +859,7 @@ struct FakeSegment bool operator<( const FakeSegment &other ) const { return m_iStartRow < other.m_iStartRow || - ( m_iStartRow == other.m_iStartRow && m_fEndBeat < other.m_fEndBeat ); + ( m_iStartRow == other.m_iStartRow && m_fLengthBeats < other.m_fLengthBeats ); } /** * @brief Compares two FakeSegments to see if one is less than or equal to the other. From fc72f2de90c857347097a06f6171e8675ee721d0 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:56:00 -0400 Subject: [PATCH 249/333] [splittiming] Prepare the editor. --- Themes/_fallback/Languages/en.ini | 2 +- src/ScreenEdit.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 4267bfe208..2c5192464e 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1231,7 +1231,7 @@ Enter a new Time Signature denominator value.=Enter the note value that represen Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. Enter a new Label value.=Enter a name for this section of the chart. -Enter a new Warp value.=Enter the beat you will warp to when you reach this point. +Enter a new Warp value.=Enter the number of beats you will warp over. Enter a new Speed percent value.=Enter the ratio for speed scrolling.\n\n1 is the default scroll. Enter a new Speed wait value.=Enter how long in seconds/beats it takes to change.\n\n0 is instant. Enter a new Speed mode value.=Enter how this segment is handled.\n\nType "0" for beats, "1" for seconds. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 95e51299b0..aa3dd8ca3f 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2763,8 +2763,11 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - GetAppropriateTiming().SetWarpAtBeat( GetBeat(), fWarp ); - SetDirty( true ); + if( fWarp > 0 ) + { + GetAppropriateTiming().SetWarpAtBeat( GetBeat(), fWarp ); + SetDirty( true ); + } } else if( SM == SM_BackFromSpeedPercentChange ) { From 388eb6bf1014f9f8234a6d5c5f69c4060c086281 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 10:57:14 -0400 Subject: [PATCH 250/333] [splittiming] Updated comment. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index aa3dd8ca3f..680a9598af 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2763,7 +2763,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - if( fWarp > 0 ) + if( fWarp >= 0 ) // allow 0 to kill a warp. { GetAppropriateTiming().SetWarpAtBeat( GetBeat(), fWarp ); SetDirty( true ); From d064547985e74d7a022b5756851a418a08bf40a4 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 22:05:23 +0700 Subject: [PATCH 251/333] [splittiming] fix TimingData.cpp --- src/TimingData.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 6c3adbd267..d2fe29d203 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -188,7 +188,7 @@ void TimingData::SetWarpAtRow( int iRow, float fNew ) { if( valid ) { - m_WarpSegments[i].m_fEndBeat = fNew; + m_WarpSegments[i].m_fLengthBeats = fNew; } else m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); @@ -308,7 +308,7 @@ void TimingData::SetFakeAtRow( int iRow, float fNew ) { if( valid ) { - m_FakeSegments[i].m_fEndBeat = fNew; + m_FakeSegments[i].m_fLengthBeats = fNew; } else m_FakeSegments.erase( m_FakeSegments.begin()+i, m_FakeSegments.begin()+i+1 ); @@ -379,7 +379,7 @@ float TimingData::GetWarpAtRow( int iWarpRow ) const { if( m_WarpSegments[i].m_iStartRow == iWarpRow ) { - return m_WarpSegments[i].m_fEndBeat; + return m_WarpSegments[i].m_fLengthBeats; } } return 0; @@ -406,7 +406,7 @@ float TimingData::GetFakeAtRow( int iFakeRow ) const { if( m_FakeSegments[i].m_iStartRow == iFakeRow ) { - return m_FakeSegments[i].m_fEndBeat; + return m_FakeSegments[i].m_fLengthBeats; } } return 0; @@ -513,7 +513,7 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const int i = GetWarpSegmentIndexAtRow( iNoteRow ); const WarpSegment& s = m_WarpSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fEndBeat) ) ) + if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) { if( m_StopSegments.empty() ) { @@ -535,7 +535,7 @@ bool TimingData::IsFakeAtRow( int iNoteRow ) const int i = GetFakeSegmentIndexAtRow( iNoteRow ); const FakeSegment& s = m_FakeSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < ( s.m_iStartRow + BeatToNoteRow(s.m_fEndBeat) ) ) + if( s.m_iStartRow <= iNoteRow && iNoteRow < ( s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) { return true; } @@ -831,10 +831,10 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float case FOUND_WARP: { bIsWarping = true; - float fWarpSum = itWS->m_fEndBeat + NoteRowToBeat( itWS->m_iStartRow ); + float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); if( fWarpSum > fWarpDestination ) { - fWarpDestination = itWS->m_fEndBeat; + fWarpDestination = fWarpSum; } iWarpBeginOut = iEventRow; fWarpDestinationOut = fWarpDestination; @@ -926,10 +926,10 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const case FOUND_WARP: { bIsWarping = true; - float fWarpSum = itWS->m_fEndBeat + NoteRowToBeat( itWS->m_iStartRow ); + float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); if( fWarpSum > fWarpDestination ) { - fWarpDestination = itWS->m_fEndBeat; + fWarpDestination = fWarpSum; } itWS ++; break; @@ -973,13 +973,13 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { const int iSegStartRow = m_WarpSegments[i].m_iStartRow; - const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_WarpSegments[i].m_fEndBeat ); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_WarpSegments[i].m_fLengthBeats ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) - m_WarpSegments[i].m_fEndBeat += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + m_WarpSegments[i].m_fLengthBeats += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_WarpSegments[i].m_fEndBeat = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale) + iStartIndex); + m_WarpSegments[i].m_fLengthBeats = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)); } if( iSegStartRow < iStartIndex ) continue; @@ -1036,13 +1036,13 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { const int iSegStartRow = m_FakeSegments[i].m_iStartRow; - const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_FakeSegments[i].m_fEndBeat ); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_FakeSegments[i].m_fLengthBeats ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) - m_FakeSegments[i].m_fEndBeat += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + m_FakeSegments[i].m_fLengthBeats += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_FakeSegments[i].m_fEndBeat = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale) + iStartIndex); + m_FakeSegments[i].m_fLengthBeats = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)); } if( iSegStartRow < iStartIndex ) continue; From c11c8db883bea75fa02c2ddc75c4418fdfb83484 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 22:06:07 +0700 Subject: [PATCH 252/333] [splittiming] it builds! time to merge. --- src/NoteField.cpp | 2 +- src/NotesWriterSSC.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 1ad62d255b..2f136a7794 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -879,7 +879,7 @@ void NoteField::DrawPrimitives() { float fBeat = NoteRowToBeat(seg->m_iStartRow); if( IS_ON_SCREEN(fBeat) ) - DrawWarpText( fBeat, seg->m_fEndBeat ); + DrawWarpText( fBeat, seg->m_fLengthBeats ); } } diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3f01843b06..fcc88c39ba 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -112,7 +112,7 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo { w.Init( "WARPS" ); FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) - w.Write( ws->m_iStartRow, ws->m_fEndBeat ); + w.Write( ws->m_iStartRow, ws->m_fLengthBeats ); w.Finish(); } @@ -143,7 +143,7 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo w.Init( "FAKES" ); FOREACH_CONST( FakeSegment, timing.m_FakeSegments, fs ) - w.Write( fs->m_iStartRow, fs->m_fEndBeat ); + w.Write( fs->m_iStartRow, fs->m_fLengthBeats ); w.Finish(); } From 2e0649f6f44265e9a89ebf009e5a60b89ba35b30 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 11:30:39 -0400 Subject: [PATCH 253/333] [splittiming] Let Fakes be edited. Also expand on some descriptions. --- Themes/_fallback/Languages/en.ini | 18 ++++++++++-------- src/ScreenEdit.cpp | 24 ++++++++++++++++++++++++ src/ScreenEdit.h | 1 + 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 2c5192464e..9b9fbf2f51 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -857,6 +857,7 @@ Edit warp=Edit warp Edit speed (percent)=Edit speed (percent) Edit speed (wait)=Edit speed (length) Edit speed (mode)=Edit speed (mode) +Edit fake=Edit fake segment Editor options=Options EditorShowBGChangesPlay=Show Backgrounds Erase step timing=Erase step timing @@ -1223,18 +1224,19 @@ Can't undo - no undo data.=Can't undo - no undo data. Do you want to revert from disk?=Do you want to revert from disk? Do you want to revert to your last save?=Do you want to revert to your last save? Do you want to save changes before exiting?=Do you want to save changes before exiting? -Enter a new BPM value.=Enter a new BPM value. -Enter a new Stop value.=Enter a new Stop value. -Enter a new Delay value.=Enter a new Delay value. +Enter a new BPM value.=Enter a new BPM value.\n\nEnter the previous value to remove. +Enter a new Stop value.=Enter a new Stop value.\n\nType "0" to remove. +Enter a new Delay value.=Enter a new Delay value.\n\nType "0" to remove. Enter a new Time Signature numerator value.=Enter the number of beats per measure. Enter a new Time Signature denominator value.=Enter the note value that represents one beat. -Enter a new Tickcount value.=Enter a new Tickcount value. -Enter a new Combo value.=Enter a new Combo value. -Enter a new Label value.=Enter a name for this section of the chart. -Enter a new Warp value.=Enter the number of beats you will warp over. -Enter a new Speed percent value.=Enter the ratio for speed scrolling.\n\n1 is the default scroll. +Enter a new Tickcount value.=Enter a new Tickcount value.\n\nEnter the previous value to remove. +Enter a new Combo value.=Enter a new Combo value.\n\nEnter the previous value to remove. +Enter a new Label value.=Enter a name for this section of the chart.\n\nEnter a previously used label to remove. +Enter a new Warp value.=Enter the number of beats you will warp over.\n\nType "0" to remove this segment. +Enter a new Speed percent value.=Enter the ratio for speed scrolling.\n\nEnter the previous value to remove.\n\n1 is the default scroll. Enter a new Speed wait value.=Enter how long in seconds/beats it takes to change.\n\n0 is instant. Enter a new Speed mode value.=Enter how this segment is handled.\n\nType "0" for beats, "1" for seconds. +Enter a new Fake value.=Enter the number of beats that won't be judged.\n\nType "0" to remove this. Are you sure you want to erase this chart's timing data?=Are you sure you want to erase this chart's timing data? Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 680a9598af..92f4f1d6aa 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -86,6 +86,7 @@ AutoScreenMessage( SM_BackFromWarpChange ); AutoScreenMessage( SM_BackFromSpeedPercentChange ); AutoScreenMessage( SM_BackFromSpeedWaitChange ); AutoScreenMessage( SM_BackFromSpeedModeChange ); +AutoScreenMessage( SM_BackFromFakeChange ); AutoScreenMessage( SM_DoEraseStepTiming ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); @@ -582,6 +583,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::speed_percent, "Edit speed (percent)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::speed_wait, "Edit speed (wait)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::speed_mode, "Edit speed (mode)", true, EditMode_Full, true, true, 0, "Beats", "Seconds" ), + MenuRowDef( ScreenEdit::fake, "Edit fake", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL ) ); @@ -2797,6 +2799,15 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } SetDirty( true ); } + else if ( SM == SM_BackFromFakeChange ) + { + float fFake = StringToFloat( ScreenTextEntry::s_sLastAnswer ); + if( fFake >= 0 ) // allow 0 to kill a warp. + { + GetAppropriateTiming().SetFakeAtBeat( GetBeat(), fFake ); + SetDirty( true ); + } + } else if( SM == SM_BackFromBGChange ) { @@ -3217,12 +3228,15 @@ void ScreenEdit::DisplayTimingMenu() RString starting = ( pTime.GetSpeedModeAtBeat( fBeat ) == 1 ? "Seconds" : "Beats" ); g_TimingDataInformation.rows[speed_mode].SetOneUnthemedChoice( starting.c_str() ); + g_TimingDataInformation.rows[fake].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetFakeAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsEditorStepTiming; g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[fake].bEnabled = GAMESTATE->m_bIsEditorStepTiming; EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } @@ -3904,6 +3918,7 @@ static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp val static LocalizedString ENTER_SPEED_PERCENT_VALUE ( "ScreenEdit", "Enter a new Speed percent value." ); static LocalizedString ENTER_SPEED_WAIT_VALUE ( "ScreenEdit", "Enter a new Speed wait value." ); static LocalizedString ENTER_SPEED_MODE_VALUE ( "ScreenEdit", "Enter a new Speed mode value." ); +static LocalizedString ENTER_FAKE_VALUE ( "ScreenEdit", "Enter a new Fake value." ); static LocalizedString CONFIRM_TIMING_ERASE ( "ScreenEdit", "Are you sure you want to erase this chart's timing data?" ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { @@ -4014,6 +4029,15 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice break; } + case fake: + { + ScreenTextEntry::TextEntry( + SM_BackFromFakeChange, + ENTER_FAKE_VALUE, + ssprintf("%.5f", GetAppropriateTiming().GetFakeAtBeat( GetBeat() ) ), + 10 + ); + } case erase_step_timing: ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); break; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index e1e3bd4435..4336517238 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -501,6 +501,7 @@ public: speed_wait, speed_mode, erase_step_timing, + fake, NUM_TIMING_DATA_INFORMATION_CHOICES }; From cb71d0a4c5ec63323975893c28ecc3914f0c5a61 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 22:39:02 +0700 Subject: [PATCH 254/333] [splittiming] allow b, B, beat, basically anything that begins with a 'b' to be recognized as beats here. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 680a9598af..11a6a3690d 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2787,7 +2787,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if ( SM == SM_BackFromSpeedModeChange ) { int tmp = StringToInt(ScreenTextEntry::s_sLastAnswer ); - if( tmp == 0 ) + if( tmp == 0 || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "b" || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "B" ) { GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 0 ); } From 161ccdeb686d535c69de3fa91fa39efb5cca6050 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 11:42:58 -0400 Subject: [PATCH 255/333] [splittiming] Implement Fake Segments...already? This was a bit fast I think. --- src/Player.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index 95878e4c1c..98483728b7 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1530,7 +1530,7 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool // Is this the row we want? do { const TapNote &tn = begin->second; - if( m_Timing->IsWarpAtRow( begin->first ) ) + if( m_Timing->IsWarpAtRow( begin->first ) || m_Timing->IsFakeAtRow( begin->first ) ) break; if( tn.type == TapNote::empty ) break; @@ -1581,7 +1581,7 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b ++iter; continue; } - if( m_Timing->IsWarpAtRow( iter.Row() ) ) + if( m_Timing->IsWarpAtRow( iter.Row() ) || m_Timing->IsFakeAtRow( iter.Row() ) ) { ++iter; continue; @@ -2100,7 +2100,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b // Stepped too close to mine? if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) && fSecondsFromExact <= GetWindowSeconds(TW_Mine) && - !m_Timing->IsWarpAtRow(iSongRow) ) + !m_Timing->IsWarpAtRow(iSongRow) && !m_Timing->IsFakeAtRow(iSongRow)) score = TNS_HitMine; break; @@ -2597,8 +2597,8 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) if( !NeedsTapJudging(tn) ) continue; - // Ignore all notes that are skipped via WARPS. - if( m_Timing->IsWarpAtRow( iter.Row() ) ) + // Ignore all notes in WarpSegments or FakeSegments. + if( m_Timing->IsWarpAtRow( iter.Row() ) || m_Timing->IsFakeAtRow( iter.Row() ) ) continue; if( tn.type == TapNote::mine ) @@ -2632,8 +2632,8 @@ void Player::UpdateJudgedRows() { int iRow = iter.Row(); - // If row is within a warp section, ignore it. -aj - if( m_Timing->IsWarpAtRow(iRow) ) + // Do not judge arrows in WarpSegments or FakeSegments + if( m_Timing->IsWarpAtRow(iRow) || m_Timing->IsFakeAtRow(iRow) ) continue; if( iLastSeenRow != iRow ) @@ -2967,8 +2967,8 @@ void Player::HandleTapRowScore( unsigned row ) bNoCheating = false; #endif - // Warp hackery. -aj - if( m_Timing->IsWarpAtRow( row ) ) + // Do not score rows in WarpSegments or FakeSegments + if( m_Timing->IsWarpAtRow( row ) || m_Timing->IsFakeAtRow( row ) ) return; if( GAMESTATE->m_bDemonstrationOrJukebox ) @@ -3071,8 +3071,8 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH bNoCheating = false; #endif - // More warp hackery. -aj - if( m_Timing->IsWarpAtRow( iRow ) ) + // WarpSegments and FakeSegments aren't judged in any way. + if( m_Timing->IsWarpAtRow( iRow ) || m_Timing->IsFakeAtRow( iRow ) ) return; // don't accumulate combo if AutoPlay is on. From 1fd19c62a7e6beafed66975b26e72fd933ca2720 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 22:44:56 +0700 Subject: [PATCH 256/333] [splittiming] input fixes --- src/ScreenEdit.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 43778456be..cce5f82bf4 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2788,15 +2788,26 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } else if ( SM == SM_BackFromSpeedModeChange ) { - int tmp = StringToInt(ScreenTextEntry::s_sLastAnswer ); - if( tmp == 0 || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "b" || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "B" ) + if( ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "b" || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "B" ) { GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 0 ); } - else + else if( ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "s" || ScreenTextEntry::s_sLastAnswer.substr(0, 1) == "S" ) { GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 1 ); } + else + { + int tmp = StringToInt(ScreenTextEntry::s_sLastAnswer ); + if( tmp == 0 ) + { + GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 0 ); + } + else + { + GetAppropriateTiming().SetSpeedModeAtBeat( GetBeat(), 1 ); + } + } SetDirty( true ); } else if ( SM == SM_BackFromFakeChange ) From c0e53205ea17a5bc50df46b6a61246fb1f2b5dd4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 11:54:58 -0400 Subject: [PATCH 257/333] [splittiming] Don't show warps on Song Timing. --- src/NoteField.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 2f136a7794..4f9c3031cf 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -873,16 +873,19 @@ void NoteField::DrawPrimitives() } // Warp text - FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg ) + if( GAMESTATE->m_bIsEditorStepTiming ) { - if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg ) { - float fBeat = NoteRowToBeat(seg->m_iStartRow); - if( IS_ON_SCREEN(fBeat) ) - DrawWarpText( fBeat, seg->m_fLengthBeats ); + if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + { + float fBeat = NoteRowToBeat(seg->m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawWarpText( fBeat, seg->m_fLengthBeats ); + } } } - + // Time Signature text FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, seg ) { From 5206fa2c8c75fd2d3d40cceffe3216e3f28af3d8 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:02:17 -0400 Subject: [PATCH 258/333] [splittiming] Show fake segments in editor. --- Themes/_fallback/metrics.ini | 3 +++ src/NoteField.cpp | 34 ++++++++++++++++++++++++++++++++++ src/NoteField.h | 1 + 3 files changed, 38 insertions(+) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 3189c3444e..d5abd2703b 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -990,6 +990,7 @@ TickcountColor=color("0,1,0,1") ComboColor=color("0.55,1,0,1") LabelColor=color("1,0,0,1") SpeedColor=color("0.5,1,1,1") +FakeColor=color("1,1,0.5,1") # BPMIsLeftSide=true StopIsLeftSide=true @@ -1000,6 +1001,7 @@ TickcountIsLeftSide=false ComboIsLeftSide=false LabelIsLeftSide=false SpeedIsLeftSide=false +FakeIsLeftSide=true # BPMOffsetX=60 StopOffsetX=50 @@ -1010,6 +1012,7 @@ TickcountOffsetX=70 ComboOffsetX=50 LabelOffsetX=130 SpeedOffsetX=30 +FakeOffsetX=90 [PlayerStageStats] # Original CVS Grading diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 4f9c3031cf..24dfddf6e4 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -455,6 +455,7 @@ static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); static ThemeMetric LABEL_COLOR ( "NoteField", "LabelColor" ); static ThemeMetric SPEED_COLOR ( "NoteField", "SpeedColor" ); +static ThemeMetric FAKE_COLOR ("NoteField", "FakeColor" ); static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); @@ -464,6 +465,7 @@ static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftS static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); static ThemeMetric LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" ); static ThemeMetric SPEED_IS_LEFT_SIDE ( "NoteField", "SpeedIsLeftSide" ); +static ThemeMetric FAKE_IS_LEFT_SIDE ( "NoteField", "FakeIsLeftSide" ); static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); @@ -473,6 +475,7 @@ static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); static ThemeMetric LABEL_OFFSETX ( "NoteField", "LabelOffsetX" ); static ThemeMetric SPEED_OFFSETX ( "NoteField", "SpeedOffsetX" ); +static ThemeMetric FAKE_OFFSETX ( "NoteField", "FakeOffsetX" ); void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { @@ -619,6 +622,23 @@ void NoteField::DrawSpeedText( const float fBeat, float fPercent, float fWait, u m_textMeasureNumber.Draw(); } +void NoteField::DrawFakeText( const float fBeat, const float fNewBeat ) +{ + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); + const float xBase = GetWidth()/2.f; + const float xOffset = FAKE_OFFSETX * fZoom; + + m_textMeasureNumber.SetZoom( fZoom ); + m_textMeasureNumber.SetHorizAlign( FAKE_IS_LEFT_SIDE ? align_right : align_left ); + m_textMeasureNumber.SetDiffuse( FAKE_COLOR ); + m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + m_textMeasureNumber.SetText( ssprintf("%.3f", fNewBeat) ); + m_textMeasureNumber.SetXY( (FAKE_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.Draw(); +} + void NoteField::DrawAttackText( const float fBeat, const Attack &attack ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); @@ -948,6 +968,20 @@ void NoteField::DrawPrimitives() } } } + + // Speed text + if( GAMESTATE->m_bIsEditorStepTiming ) + { + FOREACH_CONST( FakeSegment, timing.m_FakeSegments, seg ) + { + if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw ) + { + float fBeat = NoteRowToBeat(seg->m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawFakeText( fBeat, seg->m_fLengthBeats ); + } + } + } // Course mods text const Course *pCourse = GAMESTATE->m_pCurCourse; diff --git a/src/NoteField.h b/src/NoteField.h index b3993fd6f6..a4193f41a5 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -65,6 +65,7 @@ protected: void DrawComboText( const float fBeat, int iCombo ); void DrawLabelText( const float fBeat, RString sLabel ); void DrawSpeedText( const float fBeat, float fPercent, float fWait, unsigned short usMode ); + void DrawFakeText( const float fBeat, const float fNewBeat ); void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; From a933492f8a5f3e0956d7a28b14f25ec33a923521 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 23:05:51 +0700 Subject: [PATCH 259/333] [splittiming] allow entering both numerator and denominator of time signature at the same time (not working) --- src/ScreenEdit.cpp | 44 ++++++++++++-------------------------------- src/ScreenEdit.h | 4 +--- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index cce5f82bf4..947bb54ee9 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -77,8 +77,7 @@ AutoScreenMessage( SM_BackFromDifficultyMeterChange ); AutoScreenMessage( SM_BackFromBPMChange ); AutoScreenMessage( SM_BackFromStopChange ); AutoScreenMessage( SM_BackFromDelayChange ); -AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange ); -AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange ); +AutoScreenMessage( SM_BackFromTimeSignatureChange ); AutoScreenMessage( SM_BackFromTickcountChange ); AutoScreenMessage( SM_BackFromComboChange ); AutoScreenMessage( SM_BackFromLabelChange ); @@ -574,8 +573,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::bpm, "Edit BPM change", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::stop, "Edit stop", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::time_signature, "Edit time signature", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), @@ -2715,20 +2713,12 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) GetAppropriateTiming().SetStopAtBeat( GetBeat(), fDelay, true ); SetDirty( true ); } - else if( SM == SM_BackFromTimeSignatureNumeratorChange ) + else if( SM == SM_BackFromTimeSignatureChange ) { - int iNum = StringToInt( ScreenTextEntry::s_sLastAnswer ); - if( iNum > 0 ) + int iNum, iDen; + if( sscanf( " %d / %d ", ScreenTextEntry::s_sLastAnswer.c_str(), &iNum, &iDen ) == 2 ) { GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GetBeat(), iNum ); - } - SetDirty( true ); - } - else if ( SM == SM_BackFromTimeSignatureDenominatorChange ) - { - int iDen = StringToInt( ScreenTextEntry::s_sLastAnswer ); - if( iDen > 0) - { GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GetBeat(), iDen ); } SetDirty( true ); @@ -3227,8 +3217,7 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice( ssprintf("%d / %d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ), pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); @@ -3920,8 +3909,7 @@ static LocalizedString ENTER_BEAT_0_OFFSET ( "ScreenEdit", "Enter the offset f static LocalizedString ENTER_BPM_VALUE ( "ScreenEdit", "Enter a new BPM value." ); static LocalizedString ENTER_STOP_VALUE ( "ScreenEdit", "Enter a new Stop value." ); static LocalizedString ENTER_DELAY_VALUE ( "ScreenEdit", "Enter a new Delay value." ); -static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature numerator value." ); -static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." ); +static LocalizedString ENTER_TIME_SIGNATURE_VALUE ( "ScreenEdit", "Enter a new Time Signature." ); static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." ); static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." ); @@ -3965,20 +3953,12 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 10 ); break; - case time_signature_numerator: + case time_signature: ScreenTextEntry::TextEntry( - SM_BackFromTimeSignatureNumeratorChange, - ENTER_TIME_SIGNATURE_NUMERATOR_VALUE, - ssprintf( "%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iNumerator ), - 3 - ); - break; - case time_signature_denominator: - ScreenTextEntry::TextEntry( - SM_BackFromTimeSignatureDenominatorChange, - ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE, - ssprintf( "%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iDenominator ), - 3 + SM_BackFromTimeSignatureChange, + ENTER_TIME_SIGNATURE_VALUE, + ssprintf( "%d/%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iNumerator, GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iDenominator ), + 8 ); break; case tickcount: diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 4336517238..5bb5f6fbda 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -489,9 +489,7 @@ public: bpm, stop, delay, -// time_signature, - time_signature_numerator, - time_signature_denominator, + time_signature, label, tickcount, combo, From 59c54a563eab0097213a4d635f6c6948d015d7f8 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:08:01 -0400 Subject: [PATCH 260/333] [splittiming] Changelogs, doc cleanup. --- Docs/Changelog_SSCformat.txt | 2 ++ Docs/Changelog_sm5.txt | 8 ++++++++ Docs/SimfileFormats/ssc_msd5.txt | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index baa1f8ecc7..e5bcf25049 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -12,6 +12,8 @@ ________________________________________________________________________________ [v0.7] - theDtTvB, Wolfman2000 * Split Timing officially implemented. * #SPEEDS tag for modified scroll speeds. +* #FAKES tag for ignoring judgments within a range. +* #WARPS modified so that second parameter is now relative to the start. [v0.59] - Wolfman2000 * Typo fix: #RADARVALUES needed a semicolon at the end, not a colon. diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index fccd9d9425..64f0bacbd3 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,14 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/16 +---------- +* Added #FAKES to the SSC format. Similar to the fake arrows, these blocks + prevent all judgments within the range. [Wolfman2000] +* Changed the syntax of #WARPS slightly. Now the second value is the relative + distance that is skipped, not the absolute value when you start hitting + arrows again. [Wolfman2000] + 2011/05/15 ---------- * Added #SPEEDS to the SSC format. This multiplies your scrolling speed during diff --git a/Docs/SimfileFormats/ssc_msd5.txt b/Docs/SimfileFormats/ssc_msd5.txt index d3b7d092c1..64bad9126e 100644 --- a/Docs/SimfileFormats/ssc_msd5.txt +++ b/Docs/SimfileFormats/ssc_msd5.txt @@ -16,9 +16,10 @@ #INSTRUMENTTRACK:; #MUSICLENGTH:; #OFFSET:; +#BPMS:; #STOPS:; #DELAYS:; -#BPMS:; +#LABELS:; #TIMESIGNATURES:; #LASTBEATHINT:; #SAMPLESTART:; @@ -43,17 +44,24 @@ // information from #NOTES moved here #STEPSTYPE:; #DESCRIPTION:; +#CHARTSTYLE:; #DIFFICULTY:; #METER:; #RADARVALUES:; #CREDIT:; // steps-based timingdata +#BPMS:; #STOPS:; #DELAYS:; -#BPMS:; #TIMESIGNATURES:; -#LASTBEATHINT:; +#TICKCOUNTS:; +#COMBOS:; +#SPEEDS:; +#FAKES:; +#LABELS:; +#ATTACKS:; // Not yet in use. +#OFFSET:; // actual step data -#NOTES:; \ No newline at end of file +#NOTES:; From e902adcb13aae3e373b6eebcd3ce9967b625d59a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:12:19 -0400 Subject: [PATCH 261/333] [splittiming] FORCE clean up the cache early. --- src/Song.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index 8bf3c72fd0..c85c7eb864 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 172; +const int FILE_CACHE_VERSION = 173; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; From 0584c490a2ccd7df7ee7b97830416e82bf0238cc Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:19:42 -0400 Subject: [PATCH 262/333] [splittiming] Shrink lines. We need some way to move the ScreenTextEntry text entry down. --- Themes/_fallback/Languages/en.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 9b9fbf2f51..f06698ea5b 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1233,7 +1233,7 @@ Enter a new Tickcount value.=Enter a new Tickcount value.\n\nEnter the previous Enter a new Combo value.=Enter a new Combo value.\n\nEnter the previous value to remove. Enter a new Label value.=Enter a name for this section of the chart.\n\nEnter a previously used label to remove. Enter a new Warp value.=Enter the number of beats you will warp over.\n\nType "0" to remove this segment. -Enter a new Speed percent value.=Enter the ratio for speed scrolling.\n\nEnter the previous value to remove.\n\n1 is the default scroll. +Enter a new Speed percent value.=Enter the ratio for speed scrolling.\nEnter the previous value to remove.\n1 is the default scroll. Enter a new Speed wait value.=Enter how long in seconds/beats it takes to change.\n\n0 is instant. Enter a new Speed mode value.=Enter how this segment is handled.\n\nType "0" for beats, "1" for seconds. Enter a new Fake value.=Enter the number of beats that won't be judged.\n\nType "0" to remove this. From 399fabbf3c6be649bed4782cd815c9cdef18f3d8 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:28:18 -0400 Subject: [PATCH 263/333] [splittiming] Write only default #SPEEDS value. --- src/NotesWriterSSC.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index fcc88c39ba..fefce24b10 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -134,13 +134,14 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo w.Write( cs->m_iStartRow, cs->m_iCombo ); w.Finish(); + // Song Timing should only have the initial value. + w.Init( "SPEEDS" ); + FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) + w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode ); + w.Finish(); + if( !bIsSong ) - { - w.Init( "SPEEDS" ); - FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss ) - w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode ); - w.Finish(); - + { w.Init( "FAKES" ); FOREACH_CONST( FakeSegment, timing.m_FakeSegments, fs ) w.Write( fs->m_iStartRow, fs->m_fLengthBeats ); From e73824cad971cb13028503384bfe4f2ec161f865 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Mon, 16 May 2011 23:35:40 +0700 Subject: [PATCH 264/333] [splittiming] it works (by swapping arguments) --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 947bb54ee9..8929e4d2cd 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2716,7 +2716,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if( SM == SM_BackFromTimeSignatureChange ) { int iNum, iDen; - if( sscanf( " %d / %d ", ScreenTextEntry::s_sLastAnswer.c_str(), &iNum, &iDen ) == 2 ) + if( sscanf( ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iNum, &iDen ) == 2 ) { GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GetBeat(), iNum ); GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GetBeat(), iDen ); From 5a66df400fbf9bed28299dd0f14b089ff2312b60 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:43:44 -0400 Subject: [PATCH 265/333] [splittiming] It's working. Also, lang cleanup. --- Themes/_fallback/Languages/en.ini | 7 ++----- src/ScreenEdit.cpp | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index f06698ea5b..818a5bb456 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -847,9 +847,7 @@ Exit Edit Mode=Exit Edit Mode Edit stop=Edit stop Edit delay=Edit delay Edit Timing Data=Edit Timing Data -Edit time signature=Edit time signature (not working yet) -Edit time signature (top)=Edit time signature (beats per measure) -Edit time signature (bottom)=Edit time signature (single beat note value) +Edit time signature=Edit time signature Edit tickcount=Edit tickcount Edit combo=Edit combo Edit label=Edit label @@ -1227,8 +1225,7 @@ Do you want to save changes before exiting?=Do you want to save changes before e Enter a new BPM value.=Enter a new BPM value.\n\nEnter the previous value to remove. Enter a new Stop value.=Enter a new Stop value.\n\nType "0" to remove. Enter a new Delay value.=Enter a new Delay value.\n\nType "0" to remove. -Enter a new Time Signature numerator value.=Enter the number of beats per measure. -Enter a new Time Signature denominator value.=Enter the note value that represents one beat. +Enter a new Time Signature.=Enter a new time signature.\nUse the format "x/y".\nEnter the previous value to remove. Enter a new Tickcount value.=Enter a new Tickcount value.\n\nEnter the previous value to remove. Enter a new Combo value.=Enter a new Combo value.\n\nEnter the previous value to remove. Enter a new Label value.=Enter a name for this section of the chart.\n\nEnter a previously used label to remove. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8929e4d2cd..36e1d9febf 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2718,8 +2718,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) int iNum, iDen; if( sscanf( ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iNum, &iDen ) == 2 ) { - GetAppropriateTiming().SetTimeSignatureNumeratorAtBeat( GetBeat(), iNum ); - GetAppropriateTiming().SetTimeSignatureDenominatorAtBeat( GetBeat(), iDen ); + GetAppropriateTiming().SetTimeSignatureAtBeat( GetBeat(), iNum, iDen ); } SetDirty( true ); } From c1b72c17218b0bedc7472dfcec9d152f6f2444d9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 12:48:36 -0400 Subject: [PATCH 266/333] [splittiming] Sorry vinil! --- src/ScreenEdit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 36e1d9febf..0552e967bb 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -4027,6 +4027,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ssprintf("%.5f", GetAppropriateTiming().GetFakeAtBeat( GetBeat() ) ), 10 ); + break; } case erase_step_timing: ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO ); From 5deed76e37fabc82197e187c933f1572b7a73a79 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 17 May 2011 00:02:15 +0700 Subject: [PATCH 267/333] [splittiming] add a special case for lengthed speed change at beat 0. --- src/ArrowEffects.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 318bd75e01..a12ff397af 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -233,7 +233,11 @@ float GetSpeedMultiplier( float fSongBeat, float fMusicSeconds, const TimingData fEndTime = tim.GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - tim.GetDelayAtBeat( fStartBeat + seg.m_fWait ); } - if( fEndTime >= fCurTime && ( index > 0 || tim.m_SpeedSegments[0].m_fWait > 0.0 ) ) + if( ( index == 0 && tim.m_SpeedSegments[0].m_fWait > 0.0 ) && fCurTime < fStartTime ) + { + return 1.0; + } + else if( fEndTime >= fCurTime && ( index > 0 || tim.m_SpeedSegments[0].m_fWait > 0.0 ) ) { const float fPriorSpeed = ( index == 0 ? 1 : tim.m_SpeedSegments[index - 1].m_fPercent ); float fTimeUsed = fCurTime - fStartTime; From f00c59fd2c4b4d8b01a0d3be292117608190f2a3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 13:05:37 -0400 Subject: [PATCH 268/333] [splittiming] Allow songs to start with 0+ SPEED. Somehow, this just screams gimmickry. --- src/NotesLoaderSMA.cpp | 2 +- src/NotesLoaderSSC.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index ca2ff66c84..6a723201ab 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -321,7 +321,7 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS vector vs2; split( *s1, "=", vs2 ); - if( RowToBeat(vs2[0], iRowsPerBeat) == 0 ) // First one always seems to have 2. + if( RowToBeat(vs2[0], iRowsPerBeat) == 0 && vs2.size() == 2 ) // First one always seems to have 2. { vs2.push_back("0"); } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 5e7a9bcc68..c4f379c57e 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -140,12 +140,12 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam ) vector vs2; split( *s1, "=", vs2 ); - if( vs2[0] == 0 ) // First one always seems to have 2. + if( vs2[0] == 0 && vs2.size() == 2 ) // First one always seems to have 2. { vs2.push_back("0"); } - if( vs2.size() == 3 ) + if( vs2.size() == 3 ) // use beats by default. { vs2.push_back("0"); } From d039c5c2fb702cb9e34810dd925e2202aba8f5cb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 16:17:34 -0400 Subject: [PATCH 269/333] [splittiming] Carryover from old #WARPS code. --- src/TimingData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index d2fe29d203..9e7f064cf1 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -296,7 +296,7 @@ void TimingData::SetFakeAtRow( int iRow, float fNew ) for( i=0; i 0 && NoteRowToBeat(iRow) < fNew; + bool valid = iRow > 0 && fNew > 0; if( i == m_FakeSegments.size() ) { if( valid ) From 430de65cefa887c3d6d602d4f33d02ab85a31103 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 16:54:30 -0400 Subject: [PATCH 270/333] [splittiming] Stop repeating lua errors. Get fewer in exchange. Huh... --- NoteSkins/pump/default/UpLeft Receptor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NoteSkins/pump/default/UpLeft Receptor.lua b/NoteSkins/pump/default/UpLeft Receptor.lua index 3380a0b8ff..f6738e3c27 100644 --- a/NoteSkins/pump/default/UpLeft Receptor.lua +++ b/NoteSkins/pump/default/UpLeft Receptor.lua @@ -6,7 +6,7 @@ local function Beat(self) local part = beat%1 part = clamp(part,0,0.5) local eff = scale(part,0,0.5,1,0) - if (GAMESTATE:GetSongDelay() or false) and part == 0 then eff = 0 end + if (GAMESTATE:GetSongPosition:GetDelay() or false) and part == 0 then eff = 0 end if beat < 0 then eff = 0 end From da7226ed0a3e75f56e5bd3aa07e09279afb48ff4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 17:24:35 -0400 Subject: [PATCH 271/333] [splittiming] Revert silly mistake. --- src/global.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/global.h b/src/global.h index b90f6c86c7..e8d3c1e493 100644 --- a/src/global.h +++ b/src/global.h @@ -190,6 +190,13 @@ template struct CompileAssertDecl { }; /** @brief Use RStrings throughout the program. */ typedef StdString::CStdString RString; +#if !defined(WIN32) +/** @brief Define stricmp to be strcasecmp. */ +#define stricmp strcasecmp +/** @brief Define strnicmp to be strncasecmp. */ +#define strnicmp strncasecmp +#endif + #include "RageException.h" /* Define a few functions if necessary */ From 85133395cc9a9f278f35fe1a4de3fb79b1a9f0c3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 17:24:35 -0400 Subject: [PATCH 272/333] Right, this needs to be in default NOW. --- src/global.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/global.h b/src/global.h index b90f6c86c7..e8d3c1e493 100644 --- a/src/global.h +++ b/src/global.h @@ -190,6 +190,13 @@ template struct CompileAssertDecl { }; /** @brief Use RStrings throughout the program. */ typedef StdString::CStdString RString; +#if !defined(WIN32) +/** @brief Define stricmp to be strcasecmp. */ +#define stricmp strcasecmp +/** @brief Define strnicmp to be strncasecmp. */ +#define strnicmp strncasecmp +#endif + #include "RageException.h" /* Define a few functions if necessary */ From 5bfc05c13af7e78218fd8935e23dee0308590cb9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 17:32:00 -0400 Subject: [PATCH 273/333] [splittiming] Fix #TICKCOUNTS saving improperly. --- src/NotesLoaderKSF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 862c4bd485..3933dbbf81 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -168,7 +168,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount ); return false; } - out.m_Timing.AddTickcountSegment(TickcountSegment(0, iTickCount)); + stepsTiming.AddTickcountSegment(TickcountSegment(0, iTickCount)); } else if( sValueName=="DIFFICULTY" ) From a7bc1a01fe99a2ba7744d4021dbecf7f90edd33a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 18:37:20 -0400 Subject: [PATCH 274/333] [splittiming] Try using the LAST file, not first. Global timing can get funky if Crazy has lots of changes. Normal, on the other hand, is usally sane. Of course, if there are fewer files, it's a moot point. --- src/NotesLoaderKSF.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 3933dbbf81..385a5152fa 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -682,14 +682,16 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out ) bool bKIUCompliant = false; /* With Split Timing, there has to be a backup Song Timing in case - * anything goes wrong. Use the first file found to determine said - * timing, while also establishing whether this file respects the - * Kick It Up syntax. */ - if( !LoadGlobalData(out.GetSongDir() + arrayKSFFileNames[0], out, bKIUCompliant) ) + * anything goes wrong. As these files are kept in alphabetical + * order (hopefully), it is best to use the LAST file for timing + * purposes, for that is the "normal", or easiest difficulty. + * Usually. */ + unsigned files = arrayKSFFileNames.size(); + if( !LoadGlobalData(out.GetSongDir() + arrayKSFFileNames[files - 1], out, bKIUCompliant) ) return false; // load the Steps from the rest of the KSF files - for( unsigned i=0; i Date: Mon, 16 May 2011 23:44:06 -0400 Subject: [PATCH 275/333] [splittiming] Force tidying up of the song. This will force tidying up of the timing, thus stopping the SpeedSegment crashes. --- src/NotesLoaderDWI.cpp | 2 +- src/NotesLoaderKSF.cpp | 1 + src/NotesLoaderMidi.cpp | 3 ++- src/NotesLoaderPMS.cpp | 2 +- src/NotesLoaderSM.cpp | 3 ++- src/NotesLoaderSMA.cpp | 3 ++- src/NotesLoaderSSC.cpp | 1 + 7 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/NotesLoaderDWI.cpp b/src/NotesLoaderDWI.cpp index bd4e2314fe..1c50103288 100644 --- a/src/NotesLoaderDWI.cpp +++ b/src/NotesLoaderDWI.cpp @@ -656,7 +656,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set &Bla // do nothing. We don't care about this value name } } - + out.TidyUpData(); return true; } diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 385a5152fa..276f0c1e49 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -702,6 +702,7 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out ) out.AddSteps( pNewNotes ); } + out.TidyUpData(); return true; } diff --git a/src/NotesLoaderMidi.cpp b/src/NotesLoaderMidi.cpp index ef354d7bfe..9673cdb14d 100644 --- a/src/NotesLoaderMidi.cpp +++ b/src/NotesLoaderMidi.cpp @@ -883,7 +883,7 @@ skip_track: pSteps->SetNoteData( noteData ); songOut.AddSteps( pSteps ); } - + return true; } @@ -956,6 +956,7 @@ bool MidiLoader::LoadFromDir( const RString &sDir, Song &out ) if( !LoadFromMidi(sDir+vsFiles[0], out) ) return false; + out.TidyUpData(); return true; } diff --git a/src/NotesLoaderPMS.cpp b/src/NotesLoaderPMS.cpp index 44578f6504..f9ef5bf1cc 100644 --- a/src/NotesLoaderPMS.cpp +++ b/src/NotesLoaderPMS.cpp @@ -940,7 +940,7 @@ bool PMSLoader::LoadFromDir( const RString &sDir, Song &out ) ConvertString( out.m_sArtist, "utf-8,japanese" ); ConvertString( out.m_sGenre, "utf-8,japanese" ); - + out.TidyUpData(); return true; } diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index cd1fc8d52e..a456a6fab1 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -753,7 +753,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); } - + TidyUpData( out, bFromCache ); return true; } @@ -946,6 +946,7 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) ); } while(0); } + song.TidyUpData(); } /* diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 6a723201ab..8caba0a62b 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -711,7 +711,8 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out ) else LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() ); } - + TidyUpData(out, false); + out.TidyUpData(); return true; } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index c4f379c57e..81969e336e 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -625,6 +625,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach } } out.m_fVersion = STEPFILE_VERSION_NUMBER; + TidyUpData(out, bFromCache); return true; } From b280e775c677a53c91a9b7e9ebb5e7cf29d96572 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Mon, 16 May 2011 23:48:50 -0400 Subject: [PATCH 276/333] [splittiming] Fix order of Timing Menus. --- src/ScreenEdit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 5bb5f6fbda..d4ac2af111 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -498,8 +498,8 @@ public: speed_percent, speed_wait, speed_mode, - erase_step_timing, fake, + erase_step_timing, NUM_TIMING_DATA_INFORMATION_CHOICES }; From 1a41c32dd90d3f1a40ecd96003ba5be98a39dcd6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 00:07:43 -0400 Subject: [PATCH 277/333] [splittiming] Better variable name. ArrowEffects had a minor change, but the intent isn't up yet. It needs to be so that when you go from the editor to the chart for playing in Song Timing, it doesn't use the Step Timing. --- src/ArrowEffects.cpp | 4 ++-- src/GameState.cpp | 2 +- src/GameState.h | 4 ++-- src/NoteField.cpp | 18 +++++++++--------- src/ScreenEdit.cpp | 34 +++++++++++++++++----------------- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index a12ff397af..9f6da4ac97 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -85,7 +85,7 @@ void ArrowEffects::Update() FOREACH_PlayerNumber( pn ) { const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; - const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsEditorStepTiming) + const SongPosition &position = (GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsUsingStepTiming) ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; PerPlayerData &data = g_EffectData[pn]; @@ -264,7 +264,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float bIsPastPeakOut = true; float fYOffset = 0; - const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsEditorStepTiming) + const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsUsingStepTiming) ? pPlayerState->m_Position : GAMESTATE->m_Position; float fSongBeat = position.m_fSongBeatVisible; diff --git a/src/GameState.cpp b/src/GameState.cpp index 76bd07acd5..dbca4fc9a3 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -128,7 +128,7 @@ GameState::GameState() : m_stEditSource( Message_EditSourceStepsTypeChanged ), m_iEditCourseEntryIndex( Message_EditCourseEntryIndexChanged ), m_sEditLocalProfileID( Message_EditLocalProfileIDChanged ), - m_bIsEditorStepTiming( true ), + m_bIsUsingStepTiming( true ), m_bInStepEditor( false ) { g_pImpl = new GameStateImpl; diff --git a/src/GameState.h b/src/GameState.h index 0a6efc0e25..5e925e05ff 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -333,10 +333,10 @@ public: // Edit stuff /** - * @brief Is the editor making changes to Song timing or Steps timing? + * @brief Is the game right now using Song timing or Steps timing? * * Different options are available depending on this setting. */ - bool m_bIsEditorStepTiming; + bool m_bIsUsingStepTiming; /** * @brief Are we presently in the Step Editor, where some rules apply differently? * diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 24dfddf6e4..cdf67941c8 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -42,7 +42,7 @@ inline const TimingData *GetRealTiming(const PlayerState *pPlayerState) inline const TimingData *GetDisplayedTiming(const PlayerState *pPlayerState) { - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) return &GAMESTATE->m_pCurSong->m_SongTiming; return GetRealTiming(pPlayerState); } @@ -54,7 +54,7 @@ inline const SongPosition *GetRealPosition(const PlayerState *pPlayerState) inline const SongPosition *GetDisplayedPosition(const PlayerState *pPlayerState) { - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) return &GAMESTATE->m_Position; return GetRealPosition(pPlayerState); } @@ -739,7 +739,7 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB inline float NoteRowToVisibleBeat( const PlayerState *pPlayerState, int iRow ) { /* - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { */ return NoteRowToBeat(iRow); @@ -893,7 +893,7 @@ void NoteField::DrawPrimitives() } // Warp text - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg ) { @@ -917,7 +917,7 @@ void NoteField::DrawPrimitives() } } - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { // Tickcount text FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg ) @@ -931,7 +931,7 @@ void NoteField::DrawPrimitives() } } - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { // Combo text FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg ) @@ -956,7 +956,7 @@ void NoteField::DrawPrimitives() } } - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, seg ) { @@ -970,7 +970,7 @@ void NoteField::DrawPrimitives() } // Speed text - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { FOREACH_CONST( FakeSegment, timing.m_FakeSegments, seg ) { @@ -1004,7 +1004,7 @@ void NoteField::DrawPrimitives() } } - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) { // BGChange text switch( GAMESTATE->m_EditMode ) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0552e967bb..4b0f056f8c 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -705,7 +705,7 @@ void ScreenEdit::Init() { m_pSoundMusic = NULL; - GAMESTATE->m_bIsEditorStepTiming = true; + GAMESTATE->m_bIsUsingStepTiming = true; GAMESTATE->m_bInStepEditor = true; SubscribeToMessage( "Judgment" ); @@ -865,8 +865,8 @@ ScreenEdit::~ScreenEdit() LOG->Trace( "ScreenEdit::~ScreenEdit()" ); m_pSoundMusic->StopPlaying(); - // Reset the GameState variable in case it's needed elsewhere. - GAMESTATE->m_bIsEditorStepTiming = false; + // Go back to Step Timing on leave. + GAMESTATE->m_bIsUsingStepTiming = true; // DEFINITELY reset the InStepEditor variable. GAMESTATE->m_bInStepEditor = false; } @@ -1163,7 +1163,7 @@ void ScreenEdit::UpdateTextInfo() case EditMode_Full: sText += ssprintf( TIMING_MODE_FORMAT.GetValue(), TIMING_MODE.GetValue().c_str(), - ( GAMESTATE->m_bIsEditorStepTiming ? + ( GAMESTATE->m_bIsUsingStepTiming ? STEP_TIMING.GetValue().c_str() : SONG_TIMING.GetValue().c_str() ) ); sText += ssprintf( BEAT_0_OFFSET_FORMAT.GetValue(), @@ -1825,7 +1825,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU: case EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU: - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) { switch( EditB ) { @@ -2148,7 +2148,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) break; case EDIT_BUTTON_SWITCH_TIMINGS: - GAMESTATE->m_bIsEditorStepTiming = !GAMESTATE->m_bIsEditorStepTiming; + GAMESTATE->m_bIsUsingStepTiming = !GAMESTATE->m_bIsUsingStepTiming; m_soundSwitchTiming.Play(); break; } @@ -3147,7 +3147,7 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - TimingData &timing = GAMESTATE->m_bIsEditorStepTiming ? GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSong->m_SongTiming; + TimingData &timing = GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSong->m_SongTiming; timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } @@ -3178,7 +3178,7 @@ static void ChangeMaxBPM( const RString &sNew ) TimingData & ScreenEdit::GetAppropriateTiming() const { - if( GAMESTATE->m_bIsEditorStepTiming ) + if( GAMESTATE->m_bIsUsingStepTiming ) { return m_pSteps->m_Timing; } @@ -3187,7 +3187,7 @@ TimingData & ScreenEdit::GetAppropriateTiming() const inline void ScreenEdit::SetBeat(float fBeat) { - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) { GAMESTATE->m_Position.m_fSongBeat = fBeat; GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat = m_pSteps->m_Timing.GetBeatFromElapsedTime(m_pSong->m_SongTiming.GetElapsedTimeFromBeat(fBeat)); @@ -3201,7 +3201,7 @@ inline void ScreenEdit::SetBeat(float fBeat) inline float ScreenEdit::GetBeat() { - if( !GAMESTATE->m_bIsEditorStepTiming ) + if( !GAMESTATE->m_bIsUsingStepTiming ) { return GAMESTATE->m_Position.m_fSongBeat; } @@ -3229,13 +3229,13 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[fake].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetFakeAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsEditorStepTiming; - g_TimingDataInformation.rows[fake].bEnabled = GAMESTATE->m_bIsEditorStepTiming; + g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[fake].bEnabled = GAMESTATE->m_bIsUsingStepTiming; EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } From c26da983e4c7d0e3db34c9f3a0778459dc0a79f0 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 14:16:58 -0400 Subject: [PATCH 278/333] [splittiming] Right idea, wrong place. Song Timing respected when needed, included SpeedSegments. --- src/ArrowEffects.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 9f6da4ac97..e408967789 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -85,7 +85,7 @@ void ArrowEffects::Update() FOREACH_PlayerNumber( pn ) { const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; - const SongPosition &position = (GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsUsingStepTiming) + const SongPosition &position = GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; PerPlayerData &data = g_EffectData[pn]; @@ -264,7 +264,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float bIsPastPeakOut = true; float fYOffset = 0; - const SongPosition &position = (!GAMESTATE->m_bInStepEditor || GAMESTATE->m_bIsUsingStepTiming) + const SongPosition &position = GAMESTATE->m_bIsUsingStepTiming ? pPlayerState->m_Position : GAMESTATE->m_Position; float fSongBeat = position.m_fSongBeatVisible; @@ -277,7 +277,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float { float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; - float fSpeedMultiplier = GAMESTATE->m_bInStepEditor ? 1.0 : GetSpeedMultiplier( position.m_fSongBeatVisible, position.m_fMusicSecondsVisible, pCurSteps->m_Timing ); + float fSpeedMultiplier = ( GAMESTATE->m_bInStepEditor || !GAMESTATE->m_bIsUsingStepTiming ) ? 1.0 : GetSpeedMultiplier( position.m_fSongBeatVisible, position.m_fMusicSecondsVisible, pCurSteps->m_Timing ); fYOffset += fSpeedMultiplier * fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); } From d72a54b6512562d2b8025449ae6926e5b668017e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 14:52:07 -0400 Subject: [PATCH 279/333] [splittiming] Clean out .sm cruft. Least we can do is make sure SongTiming settings work with OpenITG. --- src/NotesWriterSM.cpp | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index cada1268d6..8261c174d6 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -134,19 +134,6 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) } } f.PutLine( ";" ); - - f.Write( "#ATTACKS:" ); - for( unsigned j = 0; j < out.m_Attacks.size(); j++ ) - { - const Attack &a = out.m_Attacks[j]; - f.Write( ssprintf( "TIME=%.2f:LEN=%.2f:MODS=%s", - a.fStartSecond, a.fSecsRemaining, a.sModifiers.c_str() ) ); - - if( j+1 < out.m_Attacks.size() ) - f.Write( ":" ); - f.PutLine( "" ); - } - f.PutLine( ";" ); f.Write( "#DELAYS:" ); for( unsigned i=0; im_iStartRow), - iter->m_iNumerator, iter->m_iDenominator ) ); - vector::const_iterator iter2 = iter; - iter2++; - if( iter2 != out.m_SongTiming.m_vTimeSignatureSegments.end() ) - f.Write( "," ); - } - f.PutLine( ";" ); - - ASSERT( !out.m_SongTiming.m_TickcountSegments.empty() ); - f.Write( "#TICKCOUNTS:" ); - for( unsigned i=0; i Date: Tue, 17 May 2011 14:55:50 -0400 Subject: [PATCH 280/333] [splittiming] Delays -> Stops at previous beat. --- src/NotesWriterSM.cpp | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index 8261c174d6..cdd27c8657 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -63,19 +63,6 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.PutLine( ssprintf( "#LYRICSPATH:%s;", SmEscape(out.m_sLyricsFile).c_str() ) ); f.PutLine( ssprintf( "#CDTITLE:%s;", SmEscape(out.m_sCDTitleFile).c_str() ) ); f.PutLine( ssprintf( "#MUSIC:%s;", SmEscape(out.m_sMusicFile).c_str() ) ); - - { - vector vs; - FOREACH_ENUM( InstrumentTrack, it ) - if( out.HasInstrumentTrack(it) ) - vs.push_back( InstrumentTrackToString(it) + - "=" + out.m_sInstrumentTrackFile[it] ); - if( !vs.empty() ) - { - RString s = join( ",", vs ); - f.PutLine( "#INSTRUMENTTRACK:" + s + ";\n" ); - } - } f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds ) ); @@ -125,30 +112,17 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) for( unsigned i=0; i Date: Tue, 17 May 2011 15:15:59 -0400 Subject: [PATCH 281/333] [splittiming] Use OpenITG settings here. --- src/NotesWriterSM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index cdd27c8657..af224d0a2b 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -214,8 +214,8 @@ static RString GetSMNotesTag( const Song &song, const Steps &in ) lines.push_back( ssprintf( " %d:", in.GetMeter() ) ); vector asRadarValues; - // SM files don't use fakes for radar data. Keep it that way. - int categories = NUM_RadarCategory - 1; + // OpenITG simfiles use 11 radar categories. + int categories = 11; FOREACH_PlayerNumber( pn ) { const RadarValues &rv = in.GetRadarValues( pn ); From 65ac4b18500f5938dcd6388750280146b4e63199 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 15:24:34 -0400 Subject: [PATCH 282/333] [splittiming] Allow Warps to be editable always. This should be the only stopping point. --- src/NotesWriterSSC.cpp | 11 ++++------- src/ScreenEdit.cpp | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index fefce24b10..77578908f8 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -108,13 +108,10 @@ static void GetTimingTags( vector &lines, TimingData timing, bool bIsSo w.Write( ss->m_iStartRow, ss->m_fStopSeconds ); w.Finish(); - if( !bIsSong ) - { - w.Init( "WARPS" ); - FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) - w.Write( ws->m_iStartRow, ws->m_fLengthBeats ); - w.Finish(); - } + w.Init( "WARPS" ); + FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws ) + w.Write( ws->m_iStartRow, ws->m_fLengthBeats ); + w.Finish(); ASSERT( !timing.m_vTimeSignatureSegments.empty() ); w.Init( "TIMESIGNATURES" ); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 4b0f056f8c..cc800e43cb 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3231,7 +3231,6 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsUsingStepTiming; - g_TimingDataInformation.rows[warp].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsUsingStepTiming; From 390776ddc76686b9e7a100d017b5204be540a5f7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 15:33:05 -0400 Subject: [PATCH 283/333] [splittiming] Relative warps in .SM, remember? --- src/NotesLoaderSM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index a456a6fab1..9237885259 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -290,7 +290,7 @@ void SMLoader::ProcessStops( TimingData &out, const RString sParam ) if( negBeat + fSkipBeats > fFreezeBeat ) fSkipBeats = fFreezeBeat - negBeat; - WarpSegment ws( negBeat, negBeat + fSkipBeats); + WarpSegment ws( negBeat, fSkipBeats); out.AddWarpSegment( ws ); negBeat = -1; From e3e16ee2e038683d1d7b329c62dbf83da9eb8182 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 16:00:05 -0400 Subject: [PATCH 284/333] [splittiming] Warps to Negs to Gone again. We're almost ready to bring this branch to default. --- src/NotesWriterSM.cpp | 27 +++++++++++++++++++++++++-- src/NotesWriterSM.h | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index af224d0a2b..55bbeeb65c 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -48,7 +48,7 @@ static RString BackgroundChangeToString( const BackgroundChange &bgc ) * @brief Write out the common tags for .SM files. * @param f the file in question. * @param out the Song in question. */ -static void WriteGlobalTags( RageFile &f, const Song &out ) +static void WriteGlobalTags( RageFile &f, Song &out ) { f.PutLine( ssprintf( "#TITLE:%s;", SmEscape(out.m_sMainTitle).c_str() ) ); f.PutLine( ssprintf( "#SUBTITLE:%s;", SmEscape(out.m_sSubTitle).c_str() ) ); @@ -107,6 +107,22 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.Write( "," ); } f.PutLine( ";" ); + + unsigned wSize = out.m_SongTiming.m_WarpSegments.size(); + if( wSize > 0 ) + { + for( unsigned i=0; i < wSize; i++ ) + { + int iRow = out.m_SongTiming.m_WarpSegments[i].m_iStartRow; + float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow); + float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].m_fLengthBeats; + StopSegment ss; + ss.m_iStartRow = iRow; + ss.m_fStopSeconds = -fSkip; + ss.m_bDelay = false; // Best to be sure. + out.m_SongTiming.AddStopSegment( ss ); + } + } f.Write( "#STOPS:" ); for( unsigned i=0; i& vpStepsToSave ) +bool NotesWriterSM::Write( RString sPath, Song &out, const vector& vpStepsToSave ) { int flags = RageFile::WRITE; diff --git a/src/NotesWriterSM.h b/src/NotesWriterSM.h index ee0ed26441..580953cdac 100644 --- a/src/NotesWriterSM.h +++ b/src/NotesWriterSM.h @@ -11,7 +11,7 @@ namespace NotesWriterSM * @param sPath the path to write the file. * @param out the Song to be written out. * @return its success or failure. */ - bool Write( RString sPath, const Song &out, const vector& vpStepsToSave ); + bool Write( RString sPath, Song &out, const vector& vpStepsToSave ); /** * @brief Get some contents about the edit file first. * @param pSong the Song in question. From 18256844e9b361dd92044b1644fc662f4be9c4ee Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 16:05:08 -0400 Subject: [PATCH 285/333] [splittiming] May as well doc this. --- Docs/Changelog_sm5.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index e244fe11f2..8a3a998b7e 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,13 @@ ________________________________________________________________________________ StepMania 5.0 $NEXT | 20110xyy -------------------------------------------------------------------------------- +2011/05/17 +---------- +* [NotesWriterSM] Write out OpenITG compatible SM files from here on out. + This includes turning Warps into Negative Stops. For those that wanted + negative BPMs specifically, my apologies, but stops are easier on math. + [Wolfman2000] + 2011/05/16 ---------- * [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) From d25b0752699dbfda8c54cf9e907544f5561481cf Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 21:32:15 -0400 Subject: [PATCH 286/333] [splittiming] See if this builds for you FSX! --- src/NotesLoader.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/NotesLoader.cpp b/src/NotesLoader.cpp index 6ed491df63..05112c51e0 100644 --- a/src/NotesLoader.cpp +++ b/src/NotesLoader.cpp @@ -43,11 +43,9 @@ bool NotesLoader::LoadFromDir( const RString &sPath, Song &out, set &Bl SMLoader::GetApplicableFiles( sPath, list ); if (!list.empty() ) return SMLoader::LoadFromDir( sPath, out ); -#if defined(_MSC_VER) || defined(MACOSX) SMALoader::GetApplicableFiles( sPath, list ); if (!list.empty() ) return SMALoader::LoadFromDir( sPath, out ); -#endif DWILoader::GetApplicableFiles( sPath, list ); if( !list.empty() ) return DWILoader::LoadFromDir( sPath, out, BlacklistedImages ); From 2af24cf6fba6881f39200dadb3d5fc161dad7282 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 23:49:18 -0400 Subject: [PATCH 287/333] Alright, let's unclip m_NoteFieldRecord! --- src/ScreenEdit.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 9d1e462c83..effa890fa0 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2342,14 +2342,6 @@ void ScreenEdit::TransitionEditState( EditState em ) // Load the player's default PlayerOptions. GAMESTATE->m_pPlayerState[PLAYER_1]->RebuildPlayerOptionsFromActiveAttacks(); - switch( em ) - { - case STATE_RECORDING: - case STATE_RECORDING_PAUSED: - PO_GROUP_ASSIGN_N( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fScrolls, PlayerOptions::SCROLL_CENTERED, 1.0f ); - break; - } - // Snap to current options. GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.SetCurrentToLevel( ModsLevel_Stage ); } From 8e775daadaab5b96f8324de8affe46b3de8a4049 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Tue, 17 May 2011 23:49:18 -0400 Subject: [PATCH 288/333] [splittiming] Stopped Centered Recording. About to transfer to default branch. --- src/ScreenEdit.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index cc800e43cb..d3680ffe05 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2418,14 +2418,6 @@ void ScreenEdit::TransitionEditState( EditState em ) // Load the player's default PlayerOptions. GAMESTATE->m_pPlayerState[PLAYER_1]->RebuildPlayerOptionsFromActiveAttacks(); - switch( em ) - { - case STATE_RECORDING: - case STATE_RECORDING_PAUSED: - PO_GROUP_ASSIGN_N( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fScrolls, PlayerOptions::SCROLL_CENTERED, 1.0f ); - break; - } - // Snap to current options. GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.SetCurrentToLevel( ModsLevel_Stage ); } From 2f1b98a7d7a1a0885a6dda53a0d483575a8e6d8f Mon Sep 17 00:00:00 2001 From: Colby Klein Date: Tue, 17 May 2011 21:07:52 -0700 Subject: [PATCH 289/333] Fix ScreenEdit recording clipping. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index effa890fa0..99e5f0b69e 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -777,7 +777,7 @@ void ScreenEdit::Init() m_NoteDataRecord.SetNumTracks( m_NoteDataEdit.GetNumTracks() ); m_NoteFieldRecord.SetXY( RECORD_X, RECORD_Y ); m_NoteFieldRecord.Init( GAMESTATE->m_pPlayerState[PLAYER_1], PLAYER_HEIGHT ); - m_NoteFieldRecord.Load( &m_NoteDataRecord, -(int)SCREEN_HEIGHT/2, (int)SCREEN_HEIGHT/2 ); + m_NoteFieldRecord.Load( &m_NoteDataRecord, -120, 425 ); this->AddChild( &m_NoteFieldRecord ); m_EditState = EditState_Invalid; From 68d86194a8ede791fec9b2d1fc09dcaac3ce8002 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 00:50:39 -0400 Subject: [PATCH 290/333] [splittiming] Don't force this file. Each individual user should have their choice. --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 7bb444fb3c..4d6915b892 100644 --- a/.hgignore +++ b/.hgignore @@ -64,6 +64,7 @@ lib*_link.a Data/UserPrefs Data/uPrefs Data/GamePrefs/*.cfg +Data/Static.ini PBProject/Hardware.plist Themes/pump Themes/optical-release From 345183e3fb0224edaeac770d7e01206294ad0cae Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 16:41:11 -0400 Subject: [PATCH 291/333] Remove renmants of XBox compilation. Hard to believe we missed these files. --- .../libtomcryptXbox-net2003.vcproj | 503 ------------------ src/libtommath/libtommathXbox-net2003.vcproj | 449 ---------------- 2 files changed, 952 deletions(-) delete mode 100644 src/libtomcrypt/libtomcryptXbox-net2003.vcproj delete mode 100644 src/libtommath/libtommathXbox-net2003.vcproj diff --git a/src/libtomcrypt/libtomcryptXbox-net2003.vcproj b/src/libtomcrypt/libtomcryptXbox-net2003.vcproj deleted file mode 100644 index cbc727d2c0..0000000000 --- a/src/libtomcrypt/libtomcryptXbox-net2003.vcproj +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libtommath/libtommathXbox-net2003.vcproj b/src/libtommath/libtommathXbox-net2003.vcproj deleted file mode 100644 index 3465ff74f6..0000000000 --- a/src/libtommath/libtommathXbox-net2003.vcproj +++ /dev/null @@ -1,449 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 0727ffa05449aed798505e2f9e19796506ce4da0 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 16:52:37 -0400 Subject: [PATCH 292/333] Test commit and bot check. If this file was added to hgignore in error, please revert. --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 7bb444fb3c..5158be428b 100644 --- a/.hgignore +++ b/.hgignore @@ -82,6 +82,7 @@ Utils/temp* BuildLog.htm *.pch +.hgrc syntax: regexp .*\#.*\#$ glob:Cache/Banners/AdditionalSongs_Airspace Preview_Derailed_Derailed bn.png From 239f0d510e7eda8b4ea1fc0fa901b18056f3a4ea Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 17:12:15 -0400 Subject: [PATCH 293/333] VS2010 conversion ignores. Also, was it mercurial.ini I had to edit? --- .hgignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgignore b/.hgignore index 5158be428b..19d2885f36 100644 --- a/.hgignore +++ b/.hgignore @@ -83,6 +83,8 @@ BuildLog.htm *.pch .hgrc +src/UpgradeLog*.XML +src/_UpgradeReport_Files syntax: regexp .*\#.*\#$ glob:Cache/Banners/AdditionalSongs_Airspace Preview_Derailed_Derailed bn.png From 3a201660c22a8276fa89f0b80c9bfdfd6b43fe06 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 17:30:35 -0400 Subject: [PATCH 294/333] Bare bones VS2010 stuff. This most likely does not work as is. It is here to allow others to try. I am unsure if the filters files are needed. --- src/StepMania-net2010.vcxproj | 2370 +++++++++++++++++++ src/libtomcrypt/libtomcrypt-net2010.vcxproj | 303 +++ src/libtommath/libtommath-net2010.vcxproj | 271 +++ src/sm-ssc-net2010.sln | 46 + 4 files changed, 2990 insertions(+) create mode 100644 src/StepMania-net2010.vcxproj create mode 100644 src/libtomcrypt/libtomcrypt-net2010.vcxproj create mode 100644 src/libtommath/libtommath-net2010.vcxproj create mode 100644 src/sm-ssc-net2010.sln diff --git a/src/StepMania-net2010.vcxproj b/src/StepMania-net2010.vcxproj new file mode 100644 index 0000000000..3584e93505 --- /dev/null +++ b/src/StepMania-net2010.vcxproj @@ -0,0 +1,2370 @@ + + + + + Debug + Win32 + + + FastDebug + Win32 + + + Release-SSE2 + Win32 + + + Release + Win32 + + + + sm-ssc + {AF209DBD-24BD-4356-8DFE-41751B221195} + StepMania + MFCProj + + + + Application + false + MultiByte + + + Application + false + MultiByte + + + Application + false + MultiByte + + + Application + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(TargetDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + true + true + $(TargetDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + false + $(TargetDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + true + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + archutils\Win32\verinc +cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ../StepMania.tlb + + + Disabled + .;..\extern\lua-5.1\src;ffmpeg\modern_working\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;WINDOWS;DEBUG;GLEW_STATIC;%(PreprocessorDefinitions) + + + EnableFastChecks + MultiThreadedDebugDLL + Use + global.h + $(IntDir)StepMania.pch + $(IntDir) + $(IntDir) + $(IntDir)vc80.pdb + + + Level4 + true + EditAndContinue + 4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) + shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;ffmpeg/modern_working/lib/avcodec.lib;ffmpeg/modern_working/lib/avformat.lib;ffmpeg/modern_working/lib/avutil.lib;ffmpeg/modern_working/lib/swscale.lib;%(AdditionalDependencies) + ../Program/StepMania-debug.exe + true + ffmpeg\lib;%(AdditionalLibraryDirectories) + wininet.lib;msimg32.lib;libci.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) + true + $(IntDir)StepMania.pdb + true + $(IntDir)$(TargetName).map + true + Windows + false + + + + + archutils\Win32\mapconv "$(IntDir)$(TargetName).map" "$(TargetDir)\StepMania-debug.vdi" + + + + + archutils\Win32\verinc +cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ../StepMania.tlb + + + /MP4 %(AdditionalOptions) + Full + AnySuitable + true + Size + .;..\extern\lua-5.1\src;ffmpeg\modern_working\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;WINDOWS;RELEASE;GLEW_STATIC;%(PreprocessorDefinitions) + true + false + + + MultiThreadedDLL + false + false + Use + global.h + $(IntDir)StepMania.pch + $(IntDir) + $(IntDir) + $(IntDir)vc80.pdb + + + Level4 + true + ProgramDatabase + 4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) + shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;ffmpeg/modern_working/lib/avcodec.lib;ffmpeg/modern_working/lib/avformat.lib;ffmpeg/modern_working/lib/avutil.lib;ffmpeg/modern_working/lib/swscale.lib;%(AdditionalDependencies) + ../Program/StepMania.exe + true + ffmpeg\lib;%(AdditionalLibraryDirectories) + wininet.lib;msimg32.lib;libci.lib;%(IgnoreSpecificDefaultLibraries) + $(IntDir)StepMania.pdb + true + $(IntDir)$(TargetName).map + true + Windows + false + + + + + archutils\Win32\mapconv "$(IntDir)$(TargetName).map" "$(TargetDir)\StepMania.vdi" + + + + + + archutils\Win32\verinc +cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ../StepMania.tlb + + + Disabled + .;..\extern\lua-5.1\src;ffmpeg\modern_working\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;WINDOWS;DEBUG;GLEW_STATIC;%(PreprocessorDefinitions) + + + Default + MultiThreadedDebugDLL + Use + global.h + $(IntDir)StepMania.pch + $(IntDir) + $(IntDir) + $(IntDir)vc80.pdb + + + Level4 + true + EditAndContinue + 4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) + shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;ffmpeg/modern_working/lib/avcodec.lib;ffmpeg/lib/avformat.lib;ffmpeg/lib/avutil.lib;ffmpeg/lib/swscale.lib;%(AdditionalDependencies) + ../Program/StepMania-fastdebug.exe + true + ffmpeg\lib;%(AdditionalLibraryDirectories) + wininet.lib;msimg32.lib;libci.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) + true + $(IntDir)StepMania.pdb + true + $(IntDir)$(TargetName).map + true + Windows + false + + + + + archutils\Win32\mapconv "$(IntDir)$(TargetName).map" "$(TargetDir)\StepMania-fastdebug.vdi" + + + + + archutils\Win32\verinc +cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ../StepMania.tlb + + + /MP4 %(AdditionalOptions) + Full + AnySuitable + true + Speed + .;..\extern\lua-5.1\src;ffmpeg\modern_working\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;WINDOWS;RELEASE;GLEW_STATIC;%(PreprocessorDefinitions) + true + false + + + MultiThreadedDLL + false + false + StreamingSIMDExtensions2 + Create + global.h + $(IntDir)StepMania-SSE2.pch + $(IntDir) + $(IntDir) + $(IntDir)vc80.pdb + + + Level4 + true + ProgramDatabase + 4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) + shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;ffmpeg/modern_working/lib/avcodec.lib;ffmpeg/modern_working/lib/avformat.lib;ffmpeg/modern_working/lib/avutil.lib;ffmpeg/modern_working/lib/swscale.lib;%(AdditionalDependencies) + ..\Program/StepMania-SSE2.exe + true + ffmpeg\lib;%(AdditionalLibraryDirectories) + wininet.lib;msimg32.lib;libci.lib;%(IgnoreSpecificDefaultLibraries) + $(IntDir)StepMania-SSE2.pdb + true + $(IntDir)$(TargetName)-SSE2.map + true + Windows + false + + + NotSet + + + archutils\Win32\mapconv "$(IntDir)$(TargetName)-SSE2.map" "$(TargetDir)\StepMania-SSE2.vdi" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HAVE_VERSION_INFO;%(PreprocessorDefinitions) + HAVE_VERSION_INFO;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {f70dd0fe-a74a-42e7-b81f-e35c49fc9eb9} + false + + + {fede5283-1518-4b1d-8124-5c54db17ea57} + false + + + + + + \ No newline at end of file diff --git a/src/libtomcrypt/libtomcrypt-net2010.vcxproj b/src/libtomcrypt/libtomcrypt-net2010.vcxproj new file mode 100644 index 0000000000..549b9f5dbe --- /dev/null +++ b/src/libtomcrypt/libtomcrypt-net2010.vcxproj @@ -0,0 +1,303 @@ + + + + + Debug + Win32 + + + Release-PGO + Win32 + + + Release-SSE2 + Win32 + + + Release + Win32 + + + + libtomcrypt + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9} + libtomcrypt + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + src\headers;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level2 + EditAndContinue + + + + + false + src\headers;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + false + src\headers;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + false + src\headers;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/libtommath/libtommath-net2010.vcxproj b/src/libtommath/libtommath-net2010.vcxproj new file mode 100644 index 0000000000..2b3119da9b --- /dev/null +++ b/src/libtommath/libtommath-net2010.vcxproj @@ -0,0 +1,271 @@ + + + + + Debug + Win32 + + + Release-PGO + Win32 + + + Release-SSE2 + Win32 + + + Release + Win32 + + + + libtommath + {FEDE5283-1518-4B1D-8124-5C54DB17EA57} + libtommath + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + .;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level2 + EditAndContinue + + + + + false + .;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + false + .;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + false + .;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Level2 + ProgramDatabase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/sm-ssc-net2010.sln b/src/sm-ssc-net2010.sln new file mode 100644 index 0000000000..f8da302dcd --- /dev/null +++ b/src/sm-ssc-net2010.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sm-ssc", "StepMania-net2010.vcxproj", "{AF209DBD-24BD-4356-8DFE-41751B221195}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtommath", "libtommath\libtommath-net2010.vcxproj", "{FEDE5283-1518-4B1D-8124-5C54DB17EA57}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtomcrypt", "libtomcrypt\libtomcrypt-net2010.vcxproj", "{F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + FastDebug|Win32 = FastDebug|Win32 + Release|Win32 = Release|Win32 + Release-SSE2|Win32 = Release-SSE2|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF209DBD-24BD-4356-8DFE-41751B221195}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.Debug|Win32.Build.0 = Debug|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.FastDebug|Win32.ActiveCfg = FastDebug|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.FastDebug|Win32.Build.0 = FastDebug|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.Release|Win32.ActiveCfg = Release|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.Release|Win32.Build.0 = Release|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.Release-SSE2|Win32.ActiveCfg = Release-SSE2|Win32 + {AF209DBD-24BD-4356-8DFE-41751B221195}.Release-SSE2|Win32.Build.0 = Release-SSE2|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Debug|Win32.ActiveCfg = Debug|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Debug|Win32.Build.0 = Debug|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.FastDebug|Win32.ActiveCfg = Debug|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.FastDebug|Win32.Build.0 = Debug|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Release|Win32.ActiveCfg = Release|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Release|Win32.Build.0 = Release|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Release-SSE2|Win32.ActiveCfg = Release-SSE2|Win32 + {FEDE5283-1518-4B1D-8124-5C54DB17EA57}.Release-SSE2|Win32.Build.0 = Release-SSE2|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Debug|Win32.ActiveCfg = Debug|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Debug|Win32.Build.0 = Debug|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.FastDebug|Win32.ActiveCfg = Debug|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.FastDebug|Win32.Build.0 = Debug|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Release|Win32.ActiveCfg = Release|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Release|Win32.Build.0 = Release|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Release-SSE2|Win32.ActiveCfg = Release-SSE2|Win32 + {F70DD0FE-A74A-42E7-B81F-E35C49FC9EB9}.Release-SSE2|Win32.Build.0 = Release-SSE2|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal From 791cd3a28f7e6d9fc9b7b8a774cac01d4301969c Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 18 May 2011 21:22:44 -0400 Subject: [PATCH 295/333] [splittiming] Prepare the cache for merging. --- src/Song.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index c85c7eb864..cca7a65b38 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 173; +const int FILE_CACHE_VERSION = 174; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; From ea301f362ea1cea3844b560870228d40dd30f471 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Thu, 19 May 2011 03:35:44 -0500 Subject: [PATCH 296/333] fix error in compat script --- Themes/_fallback/Scripts/01 compat.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/Scripts/01 compat.lua b/Themes/_fallback/Scripts/01 compat.lua index dbdf4a819c..36b5327aa2 100644 --- a/Themes/_fallback/Scripts/01 compat.lua +++ b/Themes/_fallback/Scripts/01 compat.lua @@ -72,5 +72,5 @@ end function GameState:GetSongBeat() return self:GetSongPosition():GetSongBeat() end function GameState:GetSongBeatNoOffset() return self:GetSongPosition():GetSongBeatNoOffset() end function GameState:GetSongBPS() return self:GetSongPosition():GetCurBPS() end -function GameState:GetSongDelay() return self:GetSongPosition:GetDelay() end -function GameState:GetSongFreeze() return self:GetSongPosition:GetFreeze() end +function GameState:GetSongDelay() return self:GetSongPosition():GetDelay() end +function GameState:GetSongFreeze() return self:GetSongPosition():GetFreeze() end From 29a63bcd67f2b3470e7cfbe52b434f8c14da0dce Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Thu, 19 May 2011 03:41:13 -0500 Subject: [PATCH 297/333] stepmania 5 --- Docs/Luadoc/Lua.xml | 68 ++++++++++++++++++++++++++++----------------- Docs/Luadoc/Lua.xsl | 16 +++++------ 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 6aa9eda455..942df4b4d5 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -187,8 +187,8 @@ + - @@ -519,6 +519,7 @@ + @@ -669,6 +670,7 @@ + @@ -722,12 +724,13 @@ - + + @@ -973,6 +976,7 @@ + @@ -999,6 +1003,7 @@ + @@ -1009,6 +1014,7 @@ + @@ -1074,6 +1080,7 @@ + @@ -1287,6 +1294,18 @@ + + + + + + + + + + + + @@ -1303,6 +1322,7 @@ + @@ -1349,6 +1369,7 @@ + @@ -1403,11 +1424,11 @@ + + - - @@ -1882,11 +1903,6 @@ - - - - - @@ -1978,21 +1994,23 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -2084,5 +2102,5 @@ sm-ssc v1.2.5 - 2011-05-01 + 2011-05-19 diff --git a/Docs/Luadoc/Lua.xsl b/Docs/Luadoc/Lua.xsl index 69ffebfcde..d7aabdfe4c 100644 --- a/Docs/Luadoc/Lua.xsl +++ b/Docs/Luadoc/Lua.xsl @@ -17,7 +17,7 @@ This file is automatically generated. Do not edit it. - sm-ssc Lua Information + StepMania 5 Lua Information