Revision: 8813 https://osdn.net/projects/ttssh2/scm/svn/commits/8813 Author: zmatsuo Date: 2020-06-25 00:26:40 +0900 (Thu, 25 Jun 2020) Log Message: ----------- Susie Plug-in 部を分離 - susie_plugin/ フォルダを追加 - vtdisp.c から Susie Plug-in 部分を分離して libsusieplugin.cpp,h を作成 - Unicode 化(画像ファイル名、プラグインファイル名) - 64bit対応 - libsusieplugin テスト用の spi_tester を作成 - 画像ファイルを読み込むプラグインを作成 - ttspijpeg.spi,sph - ttspipng.spi,sph - Tera Term が使う API のみ実装 Added Paths: ----------- trunk/teraterm/susie_plugin/ trunk/teraterm/susie_plugin/CMakeLists.txt trunk/teraterm/susie_plugin/build_vs2005_win32.bat trunk/teraterm/susie_plugin/extlib/ trunk/teraterm/susie_plugin/extlib/build_vs2005_win32.bat trunk/teraterm/susie_plugin/extlib/extlib.cmake trunk/teraterm/susie_plugin/extlib/extlib.md trunk/teraterm/susie_plugin/extlib/patched_file/ trunk/teraterm/susie_plugin/extlib/patched_file/libpng-1.6.37/ trunk/teraterm/susie_plugin/extlib/patched_file/libpng-1.6.37/CMakeLists.txt trunk/teraterm/susie_plugin/extlib/patched_file/zlib-1.2.11/ trunk/teraterm/susie_plugin/extlib/patched_file/zlib-1.2.11/CMakeLists.txt trunk/teraterm/susie_plugin/libsusieplugin.cpp trunk/teraterm/susie_plugin/libsusieplugin.h trunk/teraterm/susie_plugin/plugin/ trunk/teraterm/susie_plugin/plugin/spi_common.cpp trunk/teraterm/susie_plugin/plugin/spi_common.h trunk/teraterm/susie_plugin/plugin/spi_jpeg.cpp trunk/teraterm/susie_plugin/plugin/spi_png.cpp trunk/teraterm/susie_plugin/plugin/susie.def trunk/teraterm/susie_plugin/plugin/susie_plugin.h trunk/teraterm/susie_plugin/readme.md trunk/teraterm/susie_plugin/tester/ trunk/teraterm/susie_plugin/tester/spi_tester.cpp -------------- next part -------------- Added: trunk/teraterm/susie_plugin/CMakeLists.txt =================================================================== --- trunk/teraterm/susie_plugin/CMakeLists.txt (rev 0) +++ trunk/teraterm/susie_plugin/CMakeLists.txt 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.11) +project(susie_plugin) + +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /ZI /MTd") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /ZI /MTd") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") +endif() +if(NOT DEFINED EXTLIB) + set(EXTLIB "extlib") +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PLUGIN_EXT "sph") +else() + set(PLUGIN_EXT "spi") +endif() + +add_executable( + spi_tester + tester/spi_tester.cpp + libsusieplugin.cpp + libsusieplugin.h + ) + +target_include_directories( + spi_tester + PRIVATE + . + ) + +target_compile_definitions( + spi_tester + PRIVATE + WITHOUT_TERATERM + ) + +add_library( + ttspijpeg SHARED + plugin/spi_jpeg.cpp + plugin/spi_common.cpp + plugin/spi_common.h + plugin/susie.def + ) + +set_target_properties( + ttspijpeg + PROPERTIES SUFFIX ".${PLUGIN_EXT}" + ) + +target_include_directories( + ttspijpeg + PRIVATE + ${EXTLIB}/libjpeg-turbo/include +) + +target_link_libraries( + ttspijpeg + ${CMAKE_CURRENT_SOURCE_DIR}/${EXTLIB}/libjpeg-turbo/lib/jpeg-static.lib + ) + +add_library( + ttspipng SHARED + plugin/spi_png.cpp + plugin/spi_common.cpp + plugin/spi_common.h + plugin/susie.def + ) + +target_include_directories( + ttspipng + PRIVATE + ${EXTLIB}/libpng/include +) + +set_target_properties( + ttspipng + PROPERTIES SUFFIX ".${PLUGIN_EXT}" + ) + +target_link_libraries( + ttspipng + ${CMAKE_CURRENT_SOURCE_DIR}/${EXTLIB}/libpng/lib/libpng16_static.lib + ${CMAKE_CURRENT_SOURCE_DIR}/${EXTLIB}/zlib/lib/zlibstatic.lib + ) Added: trunk/teraterm/susie_plugin/build_vs2005_win32.bat =================================================================== --- trunk/teraterm/susie_plugin/build_vs2005_win32.bat (rev 0) +++ trunk/teraterm/susie_plugin/build_vs2005_win32.bat 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,7 @@ +set CMAKE=..\..\..\libs\cmake-3.11.4-win32-x86\bin\cmake.exe + +mkdir build_vs2005_win32 +cd build_vs2005_win32 +%CMAKE% -DEXTLIB=extlib/vs2005_win32 -G "Visual Studio 8 2005" .. +%CMAKE% --build . --config Release +pause Added: trunk/teraterm/susie_plugin/extlib/build_vs2005_win32.bat =================================================================== --- trunk/teraterm/susie_plugin/extlib/build_vs2005_win32.bat (rev 0) +++ trunk/teraterm/susie_plugin/extlib/build_vs2005_win32.bat 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,4 @@ +set CMAKE=..\..\..\libs\cmake-3.11.4-win32-x86\bin\cmake.exe + +%CMAKE% -DGENERATE_OPTION="-G;Visual Studio 8 2005" -DINSTALL_PREFIX_ADD="vs2005_win32/" -P extlib.cmake +pause Added: trunk/teraterm/susie_plugin/extlib/extlib.cmake =================================================================== --- trunk/teraterm/susie_plugin/extlib/extlib.cmake (rev 0) +++ trunk/teraterm/susie_plugin/extlib/extlib.cmake 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,79 @@ +set(CONFIG "Release") +#set(CONFIG "debug") +#set(GENERATE_OPTION "-G" "Visual Studio 8 2005") +#set(INSTALL_PREFIX_ADD "vs2005_win32/") + +# zlib + +file(DOWNLOAD + https://zlib.net/zlib-1.2.11.tar.xz + ./download/zlib-1.2.11.tar.xz + SHOW_PROGRESS + EXPECTED_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066 + ) + +file(MAKE_DIRECTORY "build/zlib/src") +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar -xf ${CMAKE_CURRENT_SOURCE_DIR}/download/zlib-1.2.11.tar.xz + WORKING_DIRECTORY "build/zlib/src") +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy patched_file/zlib-1.2.11/CMakeLists.txt build/zlib/src/zlib-1.2.11) +file(MAKE_DIRECTORY "build/zlib/build") +execute_process( + COMMAND ${CMAKE_COMMAND} ../src/zlib-1.2.11 -DASM686=off -DAMD64=off + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_SOURCE_DIR}/${INSTALL_PREFIX_ADD}zlib ${GENERATE_OPTION} + WORKING_DIRECTORY "build/zlib/build") +execute_process( + COMMAND ${CMAKE_COMMAND} --build . --config ${CONFIG} --target install + WORKING_DIRECTORY "build/zlib/build") + +# libpng + +file(DOWNLOAD + https://download.sourceforge.net/libpng/libpng-1.6.37.tar.xz + ./download/libpng-1.6.37.tar.xz + SHOW_PROGRESS + EXPECTED_HASH SHA256=505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca + ) + +file(MAKE_DIRECTORY "build/libpng/src") +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar -xf ${CMAKE_CURRENT_SOURCE_DIR}/download/libpng-1.6.37.tar.xz + WORKING_DIRECTORY "build/libpng/src") +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy patched_file/libpng-1.6.37/CMakeLists.txt build/libpng/src/libpng-1.6.37) + +file(MAKE_DIRECTORY "build/libpng/build") +execute_process( + COMMAND ${CMAKE_COMMAND} ../src/libpng-1.6.37 -DPNG_SHARED=off -DPNG_STATIC=on -DPNG_TESTS=off + -DPNG_DEBUG=off -DPNGARG=off -DPNG_BUILD_ZLIB=off -DZLIB_INCLUDE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/zlib/include -DZLIB_LIBRARY=${CMAKE_CURRENT_SOURCE_DIR}/zlib/lib ${GENERATE_OPTION} + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_SOURCE_DIR}/${INSTALL_PREFIX_ADD}libpng + WORKING_DIRECTORY "build/libpng/build") +execute_process( + COMMAND ${CMAKE_COMMAND} --build . --config ${CONFIG} --target install + WORKING_DIRECTORY "build/libpng/build") + +# libjpeg-turbo + +file(DOWNLOAD + https://github.com/libjpeg-turbo/libjpeg-turbo/archive/2.0.4.tar.gz + ./download/libjpeg-turbo-2.0.4.tar.gz + SHOW_PROGRESS + EXPECTED_HASH SHA256=7777c3c19762940cff42b3ba4d7cd5c52d1671b39a79532050c85efb99079064 + ) + +file(MAKE_DIRECTORY "build/libjpeg/src") +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar -xf ${CMAKE_CURRENT_SOURCE_DIR}/download/libjpeg-turbo-2.0.4.tar.gz + WORKING_DIRECTORY "build/libjpeg/src") + +file(MAKE_DIRECTORY "build/libjpeg/build") +execute_process( + COMMAND ${CMAKE_COMMAND} ../src/libjpeg-turbo-2.0.4 -DENABLE_SHARED=OFF -DWITH_SIMD=OFF + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_SOURCE_DIR}/${INSTALL_PREFIX_ADD}libjpeg-turbo ${GENERATE_OPTION} + WORKING_DIRECTORY "build/libjpeg/build") + +execute_process( + COMMAND ${CMAKE_COMMAND} --build . --config ${CONFIG} --target install + WORKING_DIRECTORY "build/libjpeg/build") + Added: trunk/teraterm/susie_plugin/extlib/extlib.md =================================================================== --- trunk/teraterm/susie_plugin/extlib/extlib.md (rev 0) +++ trunk/teraterm/susie_plugin/extlib/extlib.md 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,33 @@ +# 外部ライブラリ + +## 作成するライブラリ + +- zlib +- pnglib +- jpeglib + +## ビルド方法 + + cmake -P extlib.cmake + +### vs2019 x64 + +例 + + rmdir /s /q build + cmake -DGENERATE_OPTION="-G;Visual Studio 16 2019;-Ax64" -DINSTALL_PREFIX_ADD="vs2019_x64/" -P extlib.cmake + +### vs2019 win32 + +例 + + rmdir /s /q build + cmake -DGENERATE_OPTION="-G;Visual Studio 16 2019;-AWin32" -DINSTALL_PREFIX_ADD="vs2019_win32/" -P extlib.cmake + + +## 作業フォルダ + +ビルド後、次のフォルダは削除しても大丈夫です。 + +- build +- download Added: trunk/teraterm/susie_plugin/extlib/patched_file/libpng-1.6.37/CMakeLists.txt =================================================================== --- trunk/teraterm/susie_plugin/extlib/patched_file/libpng-1.6.37/CMakeLists.txt (rev 0) +++ trunk/teraterm/susie_plugin/extlib/patched_file/libpng-1.6.37/CMakeLists.txt 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,936 @@ +# CMakeLists.txt + +# Copyright (C) 2018 Cosmin Truta +# Copyright (C) 2007,2009-2018 Glenn Randers-Pehrson +# Written by Christian Ehrlicher, 2007 +# Revised by Roger Lowman, 2009-2010 +# Revised by Clifford Yapp, 2011-2012,2017 +# Revised by Roger Leigh, 2016 +# Revised by Andreas Franek, 2016 +# Revised by Sam Serrels, 2017 +# Revised by Vadim Barkov, 2017 +# Revised by Vicky Pfau, 2018 +# Revised by Cameron Cawley, 2018 +# Revised by Cosmin Truta, 2018 +# Revised by Kyle Bentley, 2018 + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +cmake_minimum_required(VERSION 3.1) +cmake_policy(VERSION 3.1) + +project(libpng C ASM) +enable_testing() + +set(PNGLIB_MAJOR 1) +set(PNGLIB_MINOR 6) +set(PNGLIB_RELEASE 37) +set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) +set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) + +include(GNUInstallDirs) + +# needed packages + +# Allow users to specify location of Zlib. +# Useful if zlib is being built alongside this as a sub-project. +option(PNG_BUILD_ZLIB "Custom zlib Location, else find_package is used" OFF) + +if(NOT PNG_BUILD_ZLIB) + find_package(ZLIB REQUIRED) + include_directories(${ZLIB_INCLUDE_DIR}) +endif() + +if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) + find_library(M_LIBRARY m) +else() + # libm is not needed and/or not available + set(M_LIBRARY "") +endif() + +# COMMAND LINE OPTIONS +option(PNG_SHARED "Build shared lib" ON) +option(PNG_STATIC "Build static lib" ON) +option(PNG_TESTS "Build libpng tests" ON) + +# Many more configuration options could be added here +option(PNG_FRAMEWORK "Build OS X framework" OFF) +option(PNG_DEBUG "Build with debug output" OFF) +option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON) + +set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names") +set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings") + +if(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(PNG_ARM_NEON_POSSIBLE_VALUES check on off) + set(PNG_ARM_NEON "check" CACHE STRING "Enable ARM NEON optimizations: + check: (default) use internal checking code; + off: disable the optimizations; + on: turn on unconditionally.") + set_property(CACHE PNG_ARM_NEON PROPERTY STRINGS + ${PNG_ARM_NEON_POSSIBLE_VALUES}) + list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_ARM_NEON} STREQUAL "off") + set(libpng_arm_sources + arm/arm_init.c + arm/filter_neon.S + arm/filter_neon_intrinsics.c + arm/palette_neon_intrinsics.c) + + if(${PNG_ARM_NEON} STREQUAL "on") + add_definitions(-DPNG_ARM_NEON_OPT=2) + elseif(${PNG_ARM_NEON} STREQUAL "check") + add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED) + endif() + else() + add_definitions(-DPNG_ARM_NEON_OPT=0) + endif() +endif() + +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) + set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations: + off: disable the optimizations.") + set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS + ${PNG_POWERPC_VSX_POSSIBLE_VALUES}) + list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "off") + set(libpng_powerpc_sources + powerpc/powerpc_init.c + powerpc/filter_vsx_intrinsics.c) + if(${PNG_POWERPC_VSX} STREQUAL "on") + add_definitions(-DPNG_POWERPC_VSX_OPT=2) + endif() + else() + add_definitions(-DPNG_POWERPC_VSX_OPT=0) + endif() +endif() + +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) + set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations: + off: disable the optimizations") + set_property(CACHE PNG_INTEL_SSE PROPERTY STRINGS + ${PNG_INTEL_SSE_POSSIBLE_VALUES}) + list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_INTEL_SSE} STREQUAL "off") + set(libpng_intel_sources + intel/intel_init.c + intel/filter_sse2_intrinsics.c) + if(${PNG_INTEL_SSE} STREQUAL "on") + add_definitions(-DPNG_INTEL_SSE_OPT=1) + endif() + else() + add_definitions(-DPNG_INTEL_SSE_OPT=0) + endif() +endif() + +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) + set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations: + off: disable the optimizations") + set_property(CACHE PNG_MIPS_MSA PROPERTY STRINGS + ${PNG_MIPS_MSA_POSSIBLE_VALUES}) + list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_MIPS_MSA} STREQUAL "off") + set(libpng_mips_sources + mips/mips_init.c + mips/filter_msa_intrinsics.c) + if(${PNG_MIPS_MSA} STREQUAL "on") + add_definitions(-DPNG_MIPS_MSA_OPT=2) + endif() + else() + add_definitions(-DPNG_MIPS_MSA_OPT=0) + endif() +endif() + +else(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + add_definitions(-DPNG_ARM_NEON_OPT=0) +endif() + +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + add_definitions(-DPNG_POWERPC_VSX_OPT=0) +endif() + +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + add_definitions(-DPNG_INTEL_SSE_OPT=0) +endif() + +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + add_definitions(-DPNG_MIPS_MSA_OPT=0) +endif() + +endif(PNG_HARDWARE_OPTIMIZATIONS) + +# SET LIBNAME +set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) + +# to distinguish between debug and release lib +set(CMAKE_DEBUG_POSTFIX "d") + +include(CheckCSourceCompiles) +option(ld-version-script "Enable linker version script" ON) +if(ld-version-script AND NOT APPLE) + # Check if LD supports linker scripts. + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 { + global: sym; + local: *; +}; + +VERS_2 { + global: sym2; + main; +} VERS_1; +") + set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'") + check_c_source_compiles("void sym(void) {} +void sym2(void) {} +int main(void) {return 0;} +" HAVE_LD_VERSION_SCRIPT) + if(NOT HAVE_LD_VERSION_SCRIPT) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE} "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map") + check_c_source_compiles("void sym(void) {} +void sym2(void) {} +int main(void) {return 0;} +" HAVE_SOLARIS_LD_VERSION_SCRIPT) + endif() + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE}) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map") +endif() + +# Find symbol prefix. Likely obsolete and unnecessary with recent +# toolchains (it's not done in many other projects). +function(symbol_prefix) + set(SYMBOL_PREFIX) + + execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E" "-" + INPUT_FILE /dev/null + OUTPUT_VARIABLE OUT + RESULT_VARIABLE STATUS) + + if(CPP_FAIL) + message(WARNING "Failed to run the C preprocessor") + endif() + + string(REPLACE "\n" ";" OUT "${OUT}") + foreach(line ${OUT}) + string(REGEX MATCH "^PREFIX=" found_match "${line}") + if(found_match) + string(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}") + string(REGEX MATCH "__USER_LABEL_PREFIX__" found_match "${prefix}") + if(found_match) + string(REGEX REPLACE "(.*)__USER_LABEL_PREFIX__(.*)" "\\1\\2" prefix "${prefix}") + endif() + set(SYMBOL_PREFIX "${prefix}") + endif() + endforeach() + + message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}") + set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE) +endfunction() + +if(UNIX) + symbol_prefix() +endif() + +find_program(AWK NAMES gawk awk) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +if(NOT AWK OR ANDROID) + # No awk available to generate sources; use pre-built pnglibconf.h + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) + add_custom_target(genfiles) # Dummy +else() + include(CMakeParseArguments) + # Generate .chk from .out with awk + # generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_chk) + set(options) + set(oneValueArgs INPUT OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GC_INPUT) + message(FATAL_ERROR "generate_chk: Missing INPUT argument") + endif() + if(NOT _GC_OUTPUT) + message(FATAL_ERROR "generate_chk: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${_GC_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DINPUT=${_GC_INPUT}" + "-DOUTPUT=${_GC_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake" + DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Generate .out from .c with awk + # generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_out) + set(options) + set(oneValueArgs INPUT OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GO_INPUT) + message(FATAL_ERROR "generate_out: Missing INPUT argument") + endif() + if(NOT _GO_OUTPUT) + message(FATAL_ERROR "generate_out: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${_GO_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DINPUT=${_GO_INPUT}" + "-DOUTPUT=${_GO_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake" + DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Generate specific source file with awk + # generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_source) + set(options) + set(oneValueArgs OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GSO_OUTPUT) + message(FATAL_ERROR "generate_source: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=${_GSO_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake" + DEPENDS ${_GSO_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Copy file + function(generate_copy source destination) + add_custom_command(OUTPUT "${destination}" + COMMAND "${CMAKE_COMMAND}" -E remove "${destination}" + COMMAND "${CMAKE_COMMAND}" -E copy "${source}" + "${destination}" + DEPENDS "${source}") + endfunction() + + # Generate scripts/pnglibconf.h + generate_source(OUTPUT "scripts/pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + # Generate pnglibconf.c + generate_source(OUTPUT "pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + if(PNG_PREFIX) + set(PNGLIBCONF_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst") + set(PNGPREFIX_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out") + endif() + + generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pnglibconf.h + generate_source(OUTPUT "pnglibconf.h" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + ${PNGLIBCONF_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pngprefix.h + generate_source(OUTPUT "pngprefix.h" + DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def") + + add_custom_target(symbol-check DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk") + + generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym") + generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers") + + add_custom_target(genvers DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers") + add_custom_target(gensym DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym") + + add_custom_target("genprebuilt" + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=scripts/pnglibconf.h.prebuilt" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + + # A single target handles generation of all generated files. If + # they are depended upon separately by multiple targets, this + # confuses parallel make (it would require a separate top-level + # target for each file to track the dependencies properly). + add_custom_target(genfiles DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out") +endif(NOT AWK OR ANDROID) + +# OUR SOURCES +set(libpng_public_hdrs + png.h + pngconf.h + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" +) +set(libpng_private_hdrs + pngpriv.h + pngdebug.h + pnginfo.h + pngstruct.h +) +if(AWK AND NOT ANDROID) + list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h") +endif() +set(libpng_sources + ${libpng_public_hdrs} + ${libpng_private_hdrs} + 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 + ${libpng_arm_sources} + ${libpng_intel_sources} + ${libpng_mips_sources} + ${libpng_powerpc_sources} +) +set(pngtest_sources + pngtest.c +) +set(pngvalid_sources + contrib/libtests/pngvalid.c +) +set(pngstest_sources + contrib/libtests/pngstest.c +) +set(pngunknown_sources + contrib/libtests/pngunknown.c +) +set(pngimage_sources + contrib/libtests/pngimage.c +) +set(pngfix_sources + contrib/tools/pngfix.c +) +set(png_fix_itxt_sources + contrib/tools/png-fix-itxt.c +) + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) +endif() + +if(PNG_DEBUG) + add_definitions(-DPNG_DEBUG) +endif() + +# NOW BUILD OUR TARGET +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR}) + +unset(PNG_LIB_TARGETS) + +if(PNG_SHARED) + add_library(png SHARED ${libpng_sources}) + set(PNG_LIB_TARGETS png) + set_target_properties(png PROPERTIES OUTPUT_NAME ${PNG_LIB_NAME}) + add_dependencies(png genfiles) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(png PROPERTIES PREFIX "lib") + set_target_properties(png PROPERTIES IMPORT_PREFIX "lib") + endif() + target_link_libraries(png ${ZLIB_LIBRARY} ${M_LIBRARY}) + + if(UNIX AND AWK) + if(HAVE_LD_VERSION_SCRIPT) + set_target_properties(png PROPERTIES LINK_FLAGS + "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT) + set_target_properties(png PROPERTIES LINK_FLAGS + "-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + endif() + endif() +endif() + +if(PNG_STATIC) + # does not work without changing name + set(PNG_LIB_NAME_STATIC png_static) + add_library(png_static STATIC ${libpng_sources}) + add_dependencies(png_static genfiles) + # 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_static PROPERTIES + OUTPUT_NAME "${PNG_LIB_NAME}" + CLEAN_DIRECT_OUTPUT 1) + else() + set_target_properties(png_static PROPERTIES + OUTPUT_NAME "${PNG_LIB_NAME}_static" + CLEAN_DIRECT_OUTPUT 1) + endif() + list(APPEND PNG_LIB_TARGETS png_static) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(png_static PROPERTIES PREFIX "lib") + endif() + target_link_libraries(png_static ${ZLIB_LIBRARY} ${M_LIBRARY}) + if(MSVC) + if(NOT WITH_CRT_DLL) + target_compile_options(png_static PRIVATE -MT$<$<CONFIG:Debug>:d>) + endif() + endif() +endif() + +if(PNG_FRAMEWORK) + set(PNG_LIB_NAME_FRAMEWORK png_framework) + add_library(png_framework SHARED ${libpng_sources}) + add_dependencies(png_framework genfiles) + list(APPEND PNG_LIB_TARGETS png_framework) + set_target_properties(png_framework PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION ${PNGLIB_VERSION} + MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PNGLIB_MAJOR}.${PNGLIB_MINOR} + MACOSX_FRAMEWORK_BUNDLE_VERSION ${PNGLIB_VERSION} + MACOSX_FRAMEWORK_IDENTIFIER org.libpng.libpng + XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" + PUBLIC_HEADER "${libpng_public_hdrs}" + OUTPUT_NAME png) + target_link_libraries(png_framework ${ZLIB_LIBRARY} ${M_LIBRARY}) +endif() + +if(NOT PNG_LIB_TARGETS) + message(SEND_ERROR + "No library variant selected to build. " + "Please enable at least one of the following options: " + "PNG_STATIC, PNG_SHARED, PNG_FRAMEWORK") +endif() + +if(PNG_SHARED AND WIN32) + set_target_properties(png PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) +endif() + +function(png_add_test) + set(options) + set(oneValueArgs NAME COMMAND) + set(multiValueArgs OPTIONS FILES) + cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT _PAT_NAME) + message(FATAL_ERROR "png_add_test: Missing NAME argument") + endif() + if(NOT _PAT_COMMAND) + message(FATAL_ERROR "png_add_test: Missing COMMAND argument") + endif() + + set(TEST_OPTIONS "${_PAT_OPTIONS}") + set(TEST_FILES "${_PAT_FILES}") + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/test.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake" @ONLY) + add_test(NAME "${_PAT_NAME}" + COMMAND "${CMAKE_COMMAND}" + "-DLIBPNG=$<TARGET_FILE:png>" + "-DTEST_COMMAND=$<TARGET_FILE:${_PAT_COMMAND}>" + -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake") +endfunction() + +if(PNG_TESTS AND PNG_SHARED) + # Find test PNG files by globbing, but sort lists to ensure + # consistency between different filesystems. + file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png") + list(SORT PNGSUITE_PNGS) + file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png") + list(SORT TEST_PNGS) + + set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png") + + add_executable(pngtest ${pngtest_sources}) + target_link_libraries(pngtest png) + + png_add_test(NAME pngtest COMMAND pngtest FILES "${PNGTEST_PNG}") + + add_executable(pngvalid ${pngvalid_sources}) + target_link_libraries(pngvalid png) + + png_add_test(NAME pngvalid-gamma-16-to-8 + COMMAND pngvalid OPTIONS --gamma-16-to-8) + png_add_test(NAME pngvalid-gamma-alpha-mode + COMMAND pngvalid OPTIONS --gamma-alpha-mode) + png_add_test(NAME pngvalid-gamma-background + COMMAND pngvalid OPTIONS --gamma-background) + png_add_test(NAME pngvalid-gamma-expand16-alpha-mode + COMMAND pngvalid OPTIONS --gamma-alpha-mode --expand16) + png_add_test(NAME pngvalid-gamma-expand16-background + COMMAND pngvalid OPTIONS --gamma-background --expand16) + png_add_test(NAME pngvalid-gamma-expand16-transform + COMMAND pngvalid OPTIONS --gamma-transform --expand16) + png_add_test(NAME pngvalid-gamma-sbit + COMMAND pngvalid OPTIONS --gamma-sbit) + png_add_test(NAME pngvalid-gamma-threshold + COMMAND pngvalid OPTIONS --gamma-threshold) + png_add_test(NAME pngvalid-gamma-transform + COMMAND pngvalid OPTIONS --gamma-transform) + png_add_test(NAME pngvalid-progressive-interlace-standard + COMMAND pngvalid OPTIONS --standard --progressive-read --interlace) + png_add_test(NAME pngvalid-progressive-size + COMMAND pngvalid OPTIONS --size --progressive-read) + png_add_test(NAME pngvalid-progressive-standard + COMMAND pngvalid OPTIONS --standard --progressive-read) + png_add_test(NAME pngvalid-standard + COMMAND pngvalid OPTIONS --standard) + png_add_test(NAME pngvalid-transform + COMMAND pngvalid OPTIONS --transform) + + add_executable(pngstest ${pngstest_sources}) + target_link_libraries(pngstest png) + + foreach(gamma_type 1.8 linear none sRGB) + foreach(alpha_type none alpha) + set(PNGSTEST_FILES) + foreach(test_png ${TEST_PNGS}) + string(REGEX MATCH ".*-linear[-.].*" TEST_PNG_LINEAR "${test_png}") + string(REGEX MATCH ".*-sRGB[-.].*" TEST_PNG_SRGB "${test_png}") + string(REGEX MATCH ".*-1.8[-.].*" TEST_PNG_G18 "${test_png}") + string(REGEX MATCH ".*-alpha-.*" TEST_PNG_ALPHA "${test_png}") + + set(TEST_PNG_VALID TRUE) + + if(TEST_PNG_ALPHA) + if(NOT "${alpha_type}" STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + else() + if("${alpha_type}" STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_LINEAR) + if(NOT "${gamma_type}" STREQUAL "linear") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_SRGB) + if(NOT "${gamma_type}" STREQUAL "sRGB") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_G18) + if(NOT "${gamma_type}" STREQUAL "1.8") + set(TEST_PNG_VALID FALSE) + endif() + else() + if(NOT "${gamma_type}" STREQUAL "none") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_VALID) + list(APPEND PNGSTEST_FILES "${test_png}") + endif() + endforeach() + # Should already be sorted, but sort anyway to be certain. + list(SORT PNGSTEST_FILES) + png_add_test(NAME pngstest-${gamma_type}-${alpha_type} + COMMAND pngstest + OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log + FILES ${PNGSTEST_FILES}) + endforeach() + endforeach() + + add_executable(pngunknown ${pngunknown_sources}) + target_link_libraries(pngunknown png) + + png_add_test(NAME pngunknown-discard COMMAND pngunknown OPTIONS --strict default=discard FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-IDAT COMMAND pngunknown OPTIONS --strict default=discard IDAT=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-if-safe COMMAND pngunknown OPTIONS --strict default=if-safe FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sAPI COMMAND pngunknown OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-save COMMAND pngunknown OPTIONS --strict default=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sTER COMMAND pngunknown OPTIONS --strict sTER=if-safe FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-vpAg COMMAND pngunknown OPTIONS --strict vpAg=if-safe FILES "${PNGTEST_PNG}") + + add_executable(pngimage ${pngimage_sources}) + target_link_libraries(pngimage png) + + png_add_test(NAME pngimage-quick COMMAND pngimage OPTIONS --list-combos --log FILES ${PNGSUITE_PNGS}) + png_add_test(NAME pngimage-full COMMAND pngimage OPTIONS --exhaustive --list-combos --log FILES ${PNGSUITE_PNGS}) +endif() + +if(PNG_SHARED) + add_executable(pngfix ${pngfix_sources}) + target_link_libraries(pngfix png) + set(PNG_BIN_TARGETS pngfix) + + add_executable(png-fix-itxt ${png_fix_itxt_sources}) + target_link_libraries(png-fix-itxt ${ZLIB_LIBRARY} ${M_LIBRARY}) + list(APPEND PNG_BIN_TARGETS png-fix-itxt) +endif() + +# Set a variable with CMake code which: +# Creates a symlink from src to dest (if possible) or alternatively +# copies if different. +include(CMakeParseArguments) + +function(create_symlink DEST_FILE) + + cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN}) + + if(NOT S_TARGET AND NOT S_FILE) + message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument") + endif() + + if(S_TARGET AND S_FILE) + message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.") + endif() + + if(S_FILE) + # If we don't need to symlink something that's coming from a build target, + # we can go ahead and symlink/copy at configure time. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + execute_process( + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + else() + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endif() + + if(S_TARGET) + # We need to use generator expressions, which can be a bit tricky, so for + # simplicity make the symlink a POST_BUILD step and use the TARGET + # signature of add_custom_command. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_if_different $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE}) + else() + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E create_symlink $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE}) + endif() + endif() + +endfunction() + +# Create source generation scripts. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/gensrc.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake @ONLY) + +# libpng is a library so default to 'lib' +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif() + +# CREATE PKGCONFIG FILES +# We use the same files like ./configure, so we have to set its vars. +# Only do this on Windows for Cygwin - the files don't make much sense outside +# of a UNIX look-alike. +if(NOT WIN32 OR CYGWIN OR MINGW) + set(prefix ${CMAKE_INSTALL_PREFIX}) + set(exec_prefix ${CMAKE_INSTALL_PREFIX}) + set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) + set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) + set(LIBS "-lz -lm") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY) + create_symlink(libpng.pc FILE ${PNGLIB_NAME}.pc) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY) + create_symlink(libpng-config FILE ${PNGLIB_NAME}-config) +endif() + +# SET UP LINKS +if(PNG_SHARED) + set_target_properties(png PROPERTIES +# VERSION 16.${PNGLIB_RELEASE}.1.6.37 + VERSION 16.${PNGLIB_RELEASE}.0 + SOVERSION 16 + CLEAN_DIRECT_OUTPUT 1) +endif() + +# INSTALL +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_LIB_TARGETS} + EXPORT libpng + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + if(PNG_SHARED) + # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin + if(CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET png) + install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + if(NOT WIN32) + create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png) + install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + endif() + + if(PNG_STATIC) + if(NOT WIN32 OR CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static) + install(FILES $<TARGET_LINKER_FILE_DIR:png_static>/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + 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) + if(NOT WIN32 OR CYGWIN OR MINGW) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config DESTINATION bin) + endif() +endif() + +if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_BIN_TARGETS} + RUNTIME 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 + if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW) + 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() +endif() + +# Create an export file that CMake users can include() to import our targets. +if(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-manual.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 Added: trunk/teraterm/susie_plugin/extlib/patched_file/zlib-1.2.11/CMakeLists.txt =================================================================== --- trunk/teraterm/susie_plugin/extlib/patched_file/zlib-1.2.11/CMakeLists.txt (rev 0) +++ trunk/teraterm/susie_plugin/extlib/patched_file/zlib-1.2.11/CMakeLists.txt 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,256 @@ +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +project(zlib C) + +set(VERSION "1.2.11") + +option(ASM686 "Enable building i686 assembly implementation") +option(AMD64 "Enable building amd64 assembly implementation") + +set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + +if(NOT MINGW) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + if(ASM686) + set(ZLIB_ASMS contrib/asm686/match.S) + elseif (AMD64) + set(ZLIB_ASMS contrib/amd64/amd64-match.S) + endif () + + if(ZLIB_ASMS) + add_definitions(-DASMV) + set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) + endif() +endif() + +if(MSVC) + if(ASM686) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx86/inffas32.asm + contrib/masmx86/match686.asm + ) + elseif (AMD64) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx64/gvmat64.asm + contrib/masmx64/inffasx64.asm + ) + endif() + + if(ZLIB_ASMS) + add_definitions(-DASMV -DASMINF) + endif() +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) +set_target_properties(zlib PROPERTIES SOVERSION 1) + +if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version + # encoded into their final filename. We disable this on Cygwin because + # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll + # seems to be the default. + # + # This has no effect with MSVC, on that platform the version info for + # the DLL comes from the resource file win32/zlib1.rc + set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) +endif() + +if(MSVC) + if(NOT WITH_CRT_DLL) + target_compile_options(zlib PRIVATE -MT$<$<CONFIG:Debug>:d>) + target_compile_options(zlibstatic PRIVATE -MT$<$<CONFIG:Debug>:d>) + endif() +endif() + +if(UNIX) + # On unix-like platforms the library is almost always called libz + set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +elseif(BUILD_SHARED_LIBS AND WIN32) + # Creates zlib1.dll when building shared library version + set_target_properties(zlib PROPERTIES SUFFIX "1.dll") +endif() + +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) + install(TARGETS zlib zlibstatic + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) +endif() +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") +endif() + +#============================================================================ +# Example binaries +#============================================================================ + +add_executable(example test/example.c) +target_link_libraries(example zlib) +add_test(example example) + +add_executable(minigzip test/minigzip.c) +target_link_libraries(minigzip zlib) + +if(HAVE_OFF64_T) + add_executable(example64 test/example.c) + target_link_libraries(example64 zlib) + set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + add_test(example64 example64) + + add_executable(minigzip64 test/minigzip.c) + target_link_libraries(minigzip64 zlib) + set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +endif() Added: trunk/teraterm/susie_plugin/libsusieplugin.cpp =================================================================== --- trunk/teraterm/susie_plugin/libsusieplugin.cpp (rev 0) +++ trunk/teraterm/susie_plugin/libsusieplugin.cpp 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsusieplugin.h" + +#if !defined(WITHOUT_TERATERM) +#include "layer_for_unicode.h" +#define CreateFileW _CreateFileW +#define GetFileAttributesW _GetFileAttributesW +#define GetFullPathNameW _GetFullPathNameW +#define FindFirstFileW _FindFirstFileW +#define FindNextFileW _FindNextFileW +#define LoadLibraryW _LoadLibraryW +#endif + +#if defined(_M_X64) +#define PLUGIN_EXT L".sph" +#else +#define PLUGIN_EXT L".spi" +#endif + +/** + * Susie \x83v\x83\x89\x83O\x83C\x83\x93\x82\xF0\x8Eg\x82\xC1\x82ĉ摜\x82\xF0\x93ǂݍ\x9E\x82\xDE + * + * @param[in] nameSPI \x83v\x83\x89\x83O\x83C\x83\x93\x83t\x83@\x83C\x83\x8B\x96\xBC + * @param[in] nameFile \x89摜\x83t\x83@\x83C\x83\x8B\x96\xBC(\x89摜\x82̎\xED\x97ނ肷\x82\xE9\x8DۂɎg\x82\xED\x82\xEA\x82邩\x82\xE0\x82\xB5\x82\xEA\x82Ȃ\xA2) + * @param[in] bufFile \x89摜\x83f\x81[\x83^\x82ւ̃|\x83C\x83\x93\x83^ + * @param[in] sizeFile \x89摜\x83f\x81[\x83^\x83T\x83C\x83Y + * @param[out] pHBInfo BITMAPINFO LocalFree()\x82\xB7\x82邱\x82\xC6 + * @param[out] pHBm bitmap data LocalFree()\x82\xB7\x82邱\x82\xC6 + * + * \x83v\x83\x89\x83O\x83C\x83\x93\x82\xCDUnicode\x83p\x83X\x96\xBC\x82ɑ\xB6\x8D݂\xB5\x82Ă\xE0\x83\x8D\x81[\x83h\x82ł\xAB\x82\xE9 + * \x89摜\x83t\x83@\x83C\x83\x8B\x96\xBC\x82̓v\x83\x89\x83O\x83C\x83\x93\x93\xE0\x82ő\xBD\x95\xAA\x8Eg\x97p\x82\xB3\x82\xEA\x82Ȃ\xA2 + * \x83v\x83\x89\x83O\x83C\x83\x93\x93\xE0\x82Ńt\x83@\x83C\x83\x8B\x82͈\xB5\x82\xED\x82Ȃ\xA2\x82̂\xC5 Unicode\x89\xBB\x82\xCDok\x82Ǝv\x82\xED\x82\xEA\x82\xE9 + */ +BOOL LoadPictureWithSPI(const wchar_t *nameSPI, const wchar_t *nameFile, unsigned char *bufFile, long sizeFile, HLOCAL *hbuf, + HLOCAL *hbmi) +{ + char nameFileA[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, nameFile, -1, nameFileA, _countof(nameFileA), NULL, NULL); + + HINSTANCE hSPI; + char spiVersion[8]; + int(__stdcall * SPI_IsSupported)(LPCSTR, void *); + int(__stdcall * SPI_GetPicture)(LPCSTR buf, LONG_PTR len, unsigned int flag, HANDLE *pHBInfo, HANDLE *pHBm, FARPROC, + LONG_PTR lData); + int(__stdcall * SPI_GetPluginInfo)(int, LPSTR, int); + int ret; + + ret = FALSE; + hSPI = NULL; + + // SPI \x82\xF0\x83\x8D\x81[\x83h + hSPI = LoadLibraryW(nameSPI); + + if (!hSPI) + goto error; + + FARPROC *p = (FARPROC *)&SPI_GetPluginInfo; + *p = GetProcAddress(hSPI, "GetPluginInfo"); + p = (FARPROC *)&SPI_IsSupported; + *p = GetProcAddress(hSPI, "IsSupported"); + p = (FARPROC *)&SPI_GetPicture; + *p = GetProcAddress(hSPI, "GetPicture"); + + if (!SPI_GetPluginInfo || !SPI_IsSupported || !SPI_GetPicture) + goto error; + + //\x83o\x81[\x83W\x83\x87\x83\x93\x83`\x83F\x83b\x83N + SPI_GetPluginInfo(0, spiVersion, 8); + + if (spiVersion[2] != 'I' || spiVersion[3] != 'N') + goto error; + + if (!(SPI_IsSupported)(nameFileA, bufFile)) + goto error; + + if ((SPI_GetPicture)((LPCSTR)bufFile, sizeFile, 1, hbmi, hbuf, NULL, 0)) + goto error; + + ret = TRUE; + +error: + + if (hSPI) + FreeLibrary(hSPI); + + return ret; +} + +/** + * Susie\x83v\x83\x89\x83O\x83C\x83\x93\x82\xF0\x8Eg\x82\xC1\x82ĉ摜\x83t\x83@\x83C\x83\x8B\x82\xF0\x83\x8D\x81[\x83h\x82\xB7\x82\xE9 + * \x8Ew\x92\xE8\x83t\x83H\x83\x8B\x83_\x93\xE0\x82̃v\x83\x89\x83O\x83C\x83\x93\x82\xF0\x8Eg\x82\xC1\x82ă\x8D\x81[\x83h\x82\xF0\x8E\x8E\x82݂\xE9 + * + * @param[in] image_file \x89摜\x83t\x83@\x83C\x83\x8B + * @param[in] spi_path "c:\\path\\to\\spi" + * \x82\xB1\x82̃t\x83H\x83\x8B\x83_\x82ɂ\xA0\x82\xE9\x83v\x83\x89\x83O\x83C\x83\x93\x83t\x83@\x83C\x83\x8B\x82ʼn摜\x82̃\x8D\x81[\x83h\x82\xF0\x8E\x8E\x82݂\xE9 + * \x83p\x83X\x82̍Ō\xE3\x82\xC9 "\\" \x82\xAA\x82\xA0\x82\xC1\x82Ă\xE0\x82Ȃ\xAD\x82Ă\xE0\x97ǂ\xA2 + * @param[out] pHBInfo BITMAPINFO LocalFree()\x82\xB7\x82邱\x82\xC6 + * @param[out] pHBm bitmap data LocalFree()\x82\xB7\x82邱\x82\xC6 + * @retval TRUE \x83\x8D\x81[\x83hok + * @retval FALSE \x83\x8D\x81[\x83h\x82ł\xAB\x82Ȃ\xA9\x82\xC1\x82\xBD + */ +BOOL SusieLoadPicture(const wchar_t *image_file, const wchar_t *spi_path, HANDLE *pHBInfo, HANDLE *pHBm) +{ + BOOL result = FALSE; + *pHBInfo = NULL; + *pHBm = NULL; + + //\x83t\x83@\x83C\x83\x8B\x82\xF0\x93ǂݍ\x9E\x82\xDE + HANDLE hPictureFile = CreateFileW(image_file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hPictureFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + DWORD fileSize = GetFileSize(hPictureFile, 0); + if (fileSize < 2 * 1024) { + //\x8DŒ\xE1 2kb \x82͊m\x95\xDB (Susie plugin \x82̎d\x97l\x82\xE6\x82\xE8) + fileSize = 2 * 1024; + } + unsigned char *fileBuf = (unsigned char *)malloc(fileSize); + memset(fileBuf, 0, 2*1024); //\x93\xAA\x82\xCC 2kb \x82\xCD 0 \x82ŏ\x89\x8A\xFA\x89\xBB + DWORD readByte; + ReadFile(hPictureFile, fileBuf, fileSize, &readByte, 0); + CloseHandle(hPictureFile); + + // spi_path \x82\xF0\x90\xE2\x91p\x83X\x82ɕϊ\xB7 + wchar_t spi_path_full[MAX_PATH]; + if (!GetFullPathNameW(spi_path, _countof(spi_path_full), spi_path_full, NULL)) { + goto finish; + } + wchar_t *p = wcsrchr(spi_path_full, L'\\'); + if (p != NULL) { + if (*(p + 1) == 0) { + *p = 0; // delete last '\\' + } + } + DWORD attr = GetFileAttributesW(spi_path_full); + if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { + goto finish; + } + + wchar_t spi_path_mask[MAX_PATH]; + wcsncpy_s(spi_path_mask, _countof(spi_path_mask), spi_path_full, _TRUNCATE); + wcsncat_s(spi_path_mask, _countof(spi_path_mask), L"\\*.*", _TRUNCATE); + + //\x83v\x83\x89\x83O\x83C\x83\x93\x82\xBD\x82\xC1\x82Ă\xA2\x82\xAD + WIN32_FIND_DATAW fd; + HANDLE hFind = FindFirstFileW(spi_path_mask, &fd); + if (hFind == INVALID_HANDLE_VALUE) { + goto finish; + } + do { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + const wchar_t *ext = wcsrchr(fd.cFileName, L'.'); + if (ext == NULL) { + // \x8Ag\x92\xA3\x8Eq\x82\xAA\x82Ȃ\xA2\x83t\x83@\x83C\x83\x8B? + continue; + } + if (wcscmp(ext, L".dll") != 0 && wcscmp(ext, PLUGIN_EXT) != 0) { + // .dll or .spi(or sph) \x88ȊO\x82̃t\x83@\x83C\x83\x8B + continue; + } + + wchar_t spiFileName[MAX_PATH]; + wcsncpy_s(spiFileName, _countof(spiFileName), spi_path_full, _TRUNCATE); + wcsncat_s(spiFileName, _countof(spiFileName), L"\\", _TRUNCATE); + wcsncat_s(spiFileName, _countof(spiFileName), fd.cFileName, _TRUNCATE); + + HLOCAL hbuf, hbmi; + if (LoadPictureWithSPI(spiFileName, image_file, fileBuf, fileSize, &hbuf, &hbmi)) { + *pHBInfo = hbmi; + *pHBm = hbuf; + result = TRUE; + break; + } + } while (FindNextFileW(hFind, &fd)); + FindClose(hFind); + +finish: + free(fileBuf); + return result; +} Added: trunk/teraterm/susie_plugin/libsusieplugin.h =================================================================== --- trunk/teraterm/susie_plugin/libsusieplugin.h (rev 0) +++ trunk/teraterm/susie_plugin/libsusieplugin.h 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL SusieLoadPicture(const wchar_t *image_file, const wchar_t *spi_path, HANDLE *pHBInfo, HANDLE *pHBm); + +#ifdef __cplusplus +} +#endif Added: trunk/teraterm/susie_plugin/plugin/spi_common.cpp =================================================================== --- trunk/teraterm/susie_plugin/plugin/spi_common.cpp (rev 0) +++ trunk/teraterm/susie_plugin/plugin/spi_common.cpp 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spi_common.h" + +void SPICreateBitmapInfoHeaderRGB(const unsigned char *image, int width, int height, HANDLE *phBmpInfo, HANDLE *phBmp) +{ + BITMAPINFOHEADER bmpi = {}; + bmpi.biSize = sizeof(BITMAPINFOHEADER); + bmpi.biPlanes = 1; + bmpi.biCompression = BI_RGB; + bmpi.biWidth = width; + bmpi.biHeight = height; + bmpi.biBitCount = 24; + int width4 = (width + 3) & (~3); + bmpi.biSizeImage = width4 * height * 3; + + HANDLE hBmpInfo = LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER)); + memcpy((unsigned char *)hBmpInfo, &bmpi, sizeof(bmpi)); + HANDLE hBmp = LocalAlloc(LMEM_FIXED, bmpi.biSizeImage); + unsigned char *bmp = (unsigned char *)hBmp; + + for (int y = 0; y < height; y++) { + unsigned char *dest = bmp + (y * width4 * 3); + const unsigned char *src = image + ((height - y - 1) * width * 3); + for (int x = 0; x < width; x++) { + dest[2] = src[0]; // R + dest[1] = src[1]; // G + dest[0] = src[2]; // B + dest += 3; + src += 3; + } + } + + *phBmpInfo = hBmpInfo; + *phBmp = hBmp; +} Added: trunk/teraterm/susie_plugin/plugin/spi_common.h =================================================================== --- trunk/teraterm/susie_plugin/plugin/spi_common.h (rev 0) +++ trunk/teraterm/susie_plugin/plugin/spi_common.h 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <windows.h> + +void SPICreateBitmapInfoHeaderRGB(const unsigned char *image, int width, int height, HANDLE *phBmpInfo, HANDLE *phBmp); Added: trunk/teraterm/susie_plugin/plugin/spi_jpeg.cpp =================================================================== --- trunk/teraterm/susie_plugin/plugin/spi_jpeg.cpp (rev 0) +++ trunk/teraterm/susie_plugin/plugin/spi_jpeg.cpp 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#include <setjmp.h> + +#include "jpeglib.h" +#include "spi_common.h" + +#include "susie_plugin.h" + +static void init_mem_source(j_decompress_ptr) +{ + /* no work necessary here */ +} + +static boolean fill_mem_input_buffer(j_decompress_ptr cinfo) +{ + static const JOCTET mybuffer[4] = { + (JOCTET)0xFF, (JOCTET)JPEG_EOI, 0, 0 + }; + + /* Insert a fake EOI marker */ + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + return TRUE; +} + +static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + struct jpeg_source_mgr *src = cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long)src->bytes_in_buffer) { + num_bytes -= (long)src->bytes_in_buffer; + (void)(*src->fill_input_buffer) (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->next_input_byte += (size_t)num_bytes; + src->bytes_in_buffer -= (size_t)num_bytes; + } +} + +static void term_source(j_decompress_ptr) +{ + /* no work necessary here */ +} + +static void jpeg_mem_src_tj(j_decompress_ptr cinfo, const unsigned char *inbuffer, size_t insize) +{ + struct jpeg_source_mgr *src; + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(struct jpeg_source_mgr)); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = (size_t)insize; + src->next_input_byte = (const JOCTET *)inbuffer; +} + +static void error_exit(j_common_ptr cinfo) +{ + jmp_buf *setjmp_buffer = (jmp_buf*)cinfo->client_data; + longjmp(*setjmp_buffer, 1); +} + +static int CheckHeader(const unsigned char *data, size_t len) +{ + struct jpeg_error_mgr jerr; + struct jpeg_decompress_struct dinfo; + jmp_buf setjmp_buffer; + if (setjmp(setjmp_buffer)) { + jpeg_destroy_decompress(&dinfo); + return 0; + } + dinfo.err = jpeg_std_error(&jerr); + jerr.error_exit = error_exit; + dinfo.client_data = setjmp_buffer; + jpeg_create_decompress(&dinfo); + jpeg_mem_src_tj(&dinfo, data, len); + int r = jpeg_read_header(&dinfo, TRUE); + jpeg_abort_decompress(&dinfo); + jpeg_destroy_decompress(&dinfo); + + return r == JPEG_HEADER_OK ? 1 : 0; +} + +static unsigned char *DecodeJpeg(const unsigned char *data, size_t len, int *_width, int *_height) +{ + *_width = 0; + *_height = 0; + + struct jpeg_error_mgr jerr; + struct jpeg_decompress_struct dinfo; + jmp_buf setjmp_buffer; + if (setjmp(setjmp_buffer)) { + jpeg_destroy_decompress(&dinfo); + return NULL; + } + dinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&dinfo); + jpeg_mem_src_tj(&dinfo, data, len); + int r = jpeg_read_header(&dinfo, TRUE); + if (r != JPEG_HEADER_OK) { + return NULL; + } + + int width = dinfo.image_width; + int height = dinfo.image_height; + int stride = width * 3; +// dinfo.out_color_space = JCS_EXT_BGR; + unsigned char *dstBuf = (unsigned char *)malloc(width * stride); + + JSAMPROW *row_pointer = (JSAMPROW *)malloc(sizeof(JSAMPROW) * height); + for (int i = 0; i < height; i++) { + row_pointer[i] = &dstBuf[i * (size_t)stride]; + } + + jpeg_start_decompress(&dinfo); + while (dinfo.output_scanline < dinfo.output_height) { + jpeg_read_scanlines(&dinfo, &row_pointer[dinfo.output_scanline], + dinfo.output_height - dinfo.output_scanline); + } + free(row_pointer); + jpeg_finish_decompress(&dinfo); + jpeg_destroy_decompress(&dinfo); + + *_width = width; + *_height = height; + return dstBuf; +} + +__declspec(dllexport) int __stdcall GetPluginInfo(int infono,LPSTR buf,int buflen) +{ + switch (infono){ + case 0: + strncpy_s(buf, buflen, "00IN", _TRUNCATE); + break; + default: + buf[0] = '\0'; + break; + } + return (int)strlen(buf); +} + +__declspec(dllexport) int __stdcall IsSupported(LPCSTR filename,void *dw) +{ + if (((UINT_PTR)dw & 0xffff) == 0) { + // \x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x93ǂ\xDE + (void)filename; + return 0; // \x83T\x83|\x81[\x83g\x82\xB5\x82Ȃ\xA2 + } + + const unsigned char *data = (unsigned char *)dw; + size_t len = 4 * 1024; + return CheckHeader(data, len); +} + +__declspec(dllexport) int __stdcall GetPicture(LPCSTR buf,LONG_PTR len,unsigned int flag,HANDLE *pHBInfo,HANDLE *pHBm,SUSIE_PROGRESS,LONG_PTR) +{ + if (flag != 1) { + // memory only + return 0; + } + const unsigned char *data = (unsigned char *)buf; + int width; + int height; + unsigned char *image = DecodeJpeg(data, len, &width, &height); + if (image == NULL) { + return 2; + } + + SPICreateBitmapInfoHeaderRGB(image, width, height, pHBInfo, pHBm); + free(image); + + return 0; +} Added: trunk/teraterm/susie_plugin/plugin/spi_png.cpp =================================================================== --- trunk/teraterm/susie_plugin/plugin/spi_png.cpp (rev 0) +++ trunk/teraterm/susie_plugin/plugin/spi_png.cpp 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2020 TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <stdlib.h> +#include <windows.h> + +#include "png.h" +#include "spi_common.h" + +#include "susie_plugin.h" + +typedef struct { + const unsigned char *top; + size_t len; + size_t pos; +} data_on_memory_t; + +static void PNGCBAPI read_from_memory(png_structp png_ptr, png_bytep data, size_t length) +{ + data_on_memory_t *data_on_memory = (data_on_memory_t *)png_get_io_ptr(png_ptr); + if (data_on_memory->pos + length > data_on_memory->len) { + png_error(png_ptr, "read error"); + return; + } + memcpy(data, data_on_memory->top + data_on_memory->pos, length); + data_on_memory->pos += length; +} + +static int CheckHeader(const unsigned char *data, size_t len) +{ + if (png_sig_cmp(data, 0, len)) { + return 0; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + return 0; + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return 0; + } + + data_on_memory_t data_on_memory; + data_on_memory.top = data; + data_on_memory.len = len; + data_on_memory.pos = 0; + + png_set_read_fn(png_ptr, &data_on_memory, read_from_memory); + png_read_info(png_ptr, info_ptr); + + int result = 1; + int w = png_get_image_width(png_ptr, info_ptr); + int h = png_get_image_height(png_ptr, info_ptr); + if (w == 0 || h == 0) { + result = 0; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + return result; +} + +static unsigned char *DecodePng(const unsigned char *data, size_t len, int *_width, int *_height) +{ + *_width = 0; + *_height = 0; + if (png_sig_cmp(data, 0, len)) { + return NULL; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + return NULL; + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return NULL; + } + + data_on_memory_t data_on_memory; + data_on_memory.top = data; + data_on_memory.len = len; + data_on_memory.pos = 0; + + png_set_read_fn(png_ptr, &data_on_memory, read_from_memory); + png_read_info(png_ptr, info_ptr); + + int w = png_get_image_width(png_ptr, info_ptr); + int h = png_get_image_height(png_ptr, info_ptr); + if (w == 0 || h == 0) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return NULL; + } + + int color_type = png_get_color_type(png_ptr, info_ptr); + int bit_depth = png_get_bit_depth(png_ptr, info_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); + } + if (color_type & PNG_COLOR_MASK_ALPHA) { + png_set_strip_alpha(png_ptr); + } + // png_set_bgr(png_ptr); + + unsigned char *image = (unsigned char *)malloc(w * h * 3); + if (image == NULL) { + return NULL; + } + unsigned char **pimage = (unsigned char **)malloc(h * sizeof(char *)); + if (pimage == NULL) { + return NULL; + } + unsigned char *p = image; + for (int i = 0; i < h; i++) { + pimage[i] = p; + p += w * 3; + } + png_read_image(png_ptr, pimage); + + free(pimage); + + *_width = w; + *_height = h; + return image; +} + +__declspec(dllexport) int _stdcall GetPluginInfo(int infono, LPSTR buf, int buflen) +{ + switch (infono) { + case 0: + strncpy_s(buf, buflen, "00IN", _TRUNCATE); + break; + default: + buf[0] = '\0'; + break; + } + return (int)strlen(buf); +} + +__declspec(dllexport) int __stdcall IsSupported(LPCSTR filename, void *dw) +{ + if (((UINT_PTR)dw & 0xffff) == 0) { + // \x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x93ǂ\xDE + (void)filename; + return 0; // \x83T\x83|\x81[\x83g\x82\xB5\x82Ȃ\xA2 + } + + const unsigned char *data = (unsigned char *)dw; + size_t len = 4 * 1024; + return CheckHeader(data, len); +} + +__declspec(dllexport) int __stdcall GetPicture(LPCSTR buf, LONG_PTR len, unsigned int flag, HANDLE *pHBInfo, + HANDLE *pHBm, SUSIE_PROGRESS, LONG_PTR) +{ + if (flag != 1) { + // memory only + return 0; + } + const unsigned char *data = (unsigned char *)buf; + int width; + int height; + unsigned char *image = DecodePng(data, len, &width, &height); + if (image == NULL) { + return 2; + } + + SPICreateBitmapInfoHeaderRGB(image, width, height, pHBInfo, pHBm); + free(image); + + return 0; +} Added: trunk/teraterm/susie_plugin/plugin/susie.def =================================================================== --- trunk/teraterm/susie_plugin/plugin/susie.def (rev 0) +++ trunk/teraterm/susie_plugin/plugin/susie.def 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,4 @@ +EXPORTS + GetPluginInfo + IsSupported + GetPicture Added: trunk/teraterm/susie_plugin/plugin/susie_plugin.h =================================================================== --- trunk/teraterm/susie_plugin/plugin/susie_plugin.h (rev 0) +++ trunk/teraterm/susie_plugin/plugin/susie_plugin.h 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,17 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#include <windows.h> + +// callback +typedef int(__stdcall *SUSIE_PROGRESS)(int nNum, int nDenom, LONG_PTR lData); + +__declspec(dllexport) int __stdcall GetPluginInfo(int infono, LPSTR buf, int buflen); +__declspec(dllexport) int __stdcall IsSupported(LPCSTR filename, void *dw); +__declspec(dllexport) int __stdcall GetPicture(LPCSTR buf, LONG_PTR len, unsigned int flag, HANDLE *pHBInfo, + HANDLE *pHBm, SUSIE_PROGRESS progressCallback, LONG_PTR lData); + +#ifdef __cplusplus +} +#endif Added: trunk/teraterm/susie_plugin/readme.md =================================================================== --- trunk/teraterm/susie_plugin/readme.md (rev 0) +++ trunk/teraterm/susie_plugin/readme.md 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,67 @@ +# Susie Plug-in + +Susie Plug-in は、画像ビュアーソフトSusieで様々な画像ファイルを読み込 +むための外部ファイルです。Susie 以外でも利用されています。 + +Tera Term は Susie Plug-in を使用して +画像ファイルを読み込むことができます。 + +## ファイル + +- libsusieplugin.cpp, libsusieplugin.h + - Susie Plug-in を使用するソース +- tester/ (spi_tester.exe) + - libsusieplugin テスト用プログラム +- plugin/ + - プラグインの実装 + +### プラグイン + +TeraTerm Project Team によるサンプル実装。 +Tera Term が利用するAPIのみ実装されています。 + +- ttspijpeg.dll + - jpeg 用プラグイン + - libjpeg-turbo を利用します +- ttspipng.dll + - png 用プラグイン + - libpng, zlib を利用します + +# ビルド方法 + +- cmakeでビルドします +- プラグインのビルドには zlib, libjpeg-turbo, libpng が必要です + - extlib で作成することができます + +## vs2019 win32 + +例 + + mkdir build_vs2019_win32 + cd build_vs2019_win32 + cmake -DEXTLIB=extlib/vs2019_win32 -G "Visual Studio 16 2019" -A Win32 .. + cmake --build . --config Release + +## vs2019 x64 + +例 + + mkdir build_vs2019_x64 + cd build_vs2019_x64 + cmake -DEXTLIB=extlib/vs2019_x64 -G "Visual Studio 16 2019" -A x64 .. + cmake --build . --config Release + +# Susie plugin 仕様 + +次の情報源を参考にしました。 + +- Susieダウンロード + - https://www.digitalpad.co.jp/~takechin/download.html + - https://www.digitalpad.co.jp/~takechin/archives/splug004.lzh + - PLUG_API.TXT + +- Susie プラグイン API 定義ファイル + - https://gist.github.com/tapetums/0a924712fb2fa0a7bb93 + +- TORO's Software library(Win32/Win64 Plugin) + - http://toro.d.dooo.jp/slplugin.html Added: trunk/teraterm/susie_plugin/tester/spi_tester.cpp =================================================================== --- trunk/teraterm/susie_plugin/tester/spi_tester.cpp (rev 0) +++ trunk/teraterm/susie_plugin/tester/spi_tester.cpp 2020-06-24 15:26:40 UTC (rev 8813) @@ -0,0 +1,110 @@ + +#include <stdio.h> +#include <locale.h> + +#include "libsusieplugin.h" + +static BOOL SaveBitmapFileW(const wchar_t *nameFile, const unsigned char *pbuf, const BITMAPINFO *pbmi) +{ + int bmiSize; + DWORD writtenByte; + HANDLE hFile; + BITMAPFILEHEADER bfh; + + hFile = CreateFileW(nameFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + bmiSize = pbmi->bmiHeader.biSize; + + switch (pbmi->bmiHeader.biBitCount) { + case 1: + bmiSize += pbmi->bmiHeader.biClrUsed ? sizeof(RGBQUAD) * 2 : 0; + break; + + case 2: + bmiSize += sizeof(RGBQUAD) * 4; + break; + + case 4: + bmiSize += sizeof(RGBQUAD) * 16; + break; + + case 8: + bmiSize += sizeof(RGBQUAD) * 256; + break; + } + + ZeroMemory(&bfh, sizeof(bfh)); + bfh.bfType = MAKEWORD('B', 'M'); + bfh.bfOffBits = sizeof(bfh) + bmiSize; + bfh.bfSize = bfh.bfOffBits + pbmi->bmiHeader.biSizeImage; + + WriteFile(hFile, &bfh, sizeof(bfh), &writtenByte, 0); + WriteFile(hFile, pbmi, bmiSize, &writtenByte, 0); + WriteFile(hFile, pbuf, pbmi->bmiHeader.biSizeImage, &writtenByte, 0); + + CloseHandle(hFile); + + return TRUE; +} + +int test_main(const wchar_t *fname_in, const wchar_t *spi_dir, const wchar_t *fname_out) +{ + wprintf(L"in '%s'\n", fname_in); + wprintf(L"dir '%s'\n", spi_dir); + wprintf(L"out '%s'\n", fname_out); + + HANDLE hbmi; + HANDLE hbuf; + BOOL r = SusieLoadPicture(fname_in, spi_dir, &hbmi, &hbuf); + if (!r) { + printf("can not read\n"); + return 0; + } + SaveBitmapFileW(fname_out, (unsigned char *)hbuf, (BITMAPINFO *)hbmi); + LocalFree(hbmi); + LocalFree(hbuf); + return 0; +} + +#if 0 +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, ""); + if (argc != 4) { + printf( + "spi_test [readfile] [spi_dir] [writefile]\n" + "example:\n" + " spi_test lena.jpg ./debug lena.bmp\n"); + return 0; + } + + wchar_t fname_in[MAX_PATH]; + wchar_t spi_dir[MAX_PATH]; + wchar_t fname_out[MAX_PATH]; + MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, argv[1], -1, fname_in, _countof(fname_in)); + MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, argv[2], -1, spi_dir, _countof(spi_dir)); + MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, argv[3], -1, fname_out, _countof(fname_out)); + int r = test_main(fname_in, spi_dir, fname_out); + return r; +} +#else +int wmain(int argc, wchar_t *argv[]) +{ + setlocale(LC_ALL, ""); + if (argc != 4) { + printf( + "spi_test [readfile] [spi_dir] [writefile]\n" + "example:\n" + " spi_test lena.jpg ./debug lena.bmp\n"); + return 0; + } + + const wchar_t *fname_in = argv[1]; + const wchar_t *spi_dir = argv[2]; + const wchar_t *fname_out = argv[3]; + int r = test_main(fname_in, spi_dir, fname_out); + return r; +} +#endif