mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-31 20:51:12 -06:00
Merge branch 'master' of https://github.com/prusa3d/Slic3r
This commit is contained in:
commit
9bc93134f9
471 changed files with 12650 additions and 125974 deletions
|
|
@ -21,30 +21,6 @@ add_subdirectory(libnest2d)
|
|||
include_directories(${LIBDIR}/qhull/src)
|
||||
#message(STATUS ${LIBDIR}/qhull/src)
|
||||
|
||||
# ##############################################################################
|
||||
# Configure rasterizer target
|
||||
# ##############################################################################
|
||||
|
||||
find_package(PNG QUIET)
|
||||
|
||||
option(RASTERIZER_FORCE_BUILTIN_LIBPNG "Force the usage of builting libpng instead of the system version." OFF)
|
||||
|
||||
if(PNG_FOUND AND NOT RASTERIZER_FORCE_BUILTIN_LIBPNG)
|
||||
message(STATUS "Using system libpng.")
|
||||
else()
|
||||
set(ZLIB_LIBRARY "")
|
||||
message(WARNING "Using builtin libpng. This can cause crashes on some platforms.")
|
||||
set(SKIP_INSTALL_ALL 1) # Prevent png+zlib from creating install targets
|
||||
add_subdirectory(png/zlib)
|
||||
set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
add_subdirectory(png/libpng)
|
||||
set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(png_static PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set(PNG_LIBRARIES png_static zlibstatic)
|
||||
set(PNG_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/png/libpng ${CMAKE_CURRENT_BINARY_DIR}/png/libpng)
|
||||
endif()
|
||||
|
||||
add_subdirectory(libslic3r)
|
||||
|
||||
if (SLIC3R_GUI)
|
||||
|
|
@ -60,10 +36,12 @@ if (SLIC3R_GUI)
|
|||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (wxWidgets_CONFIG_OPTIONS "--toolkit=gtk${SLIC3R_GTK}")
|
||||
if (SLIC3R_WX_STABLE)
|
||||
find_package(wxWidgets 3.0 REQUIRED COMPONENTS base core adv html gl)
|
||||
else ()
|
||||
find_package(wxWidgets 3.1 QUIET COMPONENTS base core adv html gl)
|
||||
|
||||
if (NOT wxWidgets_FOUND)
|
||||
message(FATAL_ERROR "\nCould not find wxWidgets 3.1.\n"
|
||||
"Hint: On Linux you can set -DSLIC3R_WX_STABLE=1 to use wxWidgets 3.0\n")
|
||||
|
|
@ -115,12 +93,16 @@ endif ()
|
|||
|
||||
# Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries.
|
||||
if (SLIC3R_GUI)
|
||||
target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES})
|
||||
target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES})
|
||||
|
||||
# Configure libcurl & OpenSSL
|
||||
# Configure libcurl and its dependencies OpenSSL & zlib
|
||||
find_package(CURL REQUIRED)
|
||||
if (NOT MSVC)
|
||||
# Required by libcurl
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
target_include_directories(slic3r PRIVATE ${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(slic3r CURL::libcurl)
|
||||
target_link_libraries(slic3r ${CURL_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||
if (SLIC3R_STATIC)
|
||||
if (NOT APPLE)
|
||||
# libcurl is always linked dynamically to the system libcurl on OSX.
|
||||
|
|
@ -155,7 +137,7 @@ if (MSVC)
|
|||
add_executable(slic3r_app_gui WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
||||
add_dependencies(slic3r_app_gui slic3r)
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r")
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r" PDB_NAME "slic3r_gui")
|
||||
|
||||
add_executable(slic3r_app_console slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||
|
|
@ -188,7 +170,7 @@ if (MSVC)
|
|||
)
|
||||
endif ()
|
||||
elseif (XCODE)
|
||||
# Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level
|
||||
# Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level
|
||||
add_custom_command(TARGET slic3r POST_BUILD
|
||||
COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/resources"
|
||||
COMMENT "Symlinking the resources directory into the build tree"
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ static void stl_record_neighbors(stl_file *stl,
|
|||
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
|
||||
static void stl_initialize_facet_check_exact(stl_file *stl);
|
||||
static void stl_initialize_facet_check_nearby(stl_file *stl);
|
||||
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
|
||||
stl_vertex *a, stl_vertex *b);
|
||||
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b);
|
||||
static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
|
||||
stl_vertex *a, stl_vertex *b, float tolerance);
|
||||
static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
||||
|
|
@ -60,41 +59,40 @@ extern int stl_check_normal_vector(stl_file *stl,
|
|||
int facet_num, int normal_fix_flag);
|
||||
static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
|
||||
|
||||
|
||||
void
|
||||
stl_check_facets_exact(stl_file *stl) {
|
||||
/* This function builds the neighbors list. No modifications are made
|
||||
* to any of the facets. The edges are said to match only if all six
|
||||
* floats of the first edge matches all six floats of the second edge.
|
||||
*/
|
||||
|
||||
stl_hash_edge edge;
|
||||
stl_facet facet;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (stl->error) return;
|
||||
// This function builds the neighbors list. No modifications are made
|
||||
// to any of the facets. The edges are said to match only if all six
|
||||
// floats of the first edge matches all six floats of the second edge.
|
||||
void stl_check_facets_exact(stl_file *stl)
|
||||
{
|
||||
if (stl->error)
|
||||
return;
|
||||
|
||||
stl->stats.connected_edges = 0;
|
||||
stl->stats.connected_facets_1_edge = 0;
|
||||
stl->stats.connected_facets_2_edge = 0;
|
||||
stl->stats.connected_facets_3_edge = 0;
|
||||
|
||||
stl_initialize_facet_check_exact(stl);
|
||||
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
|
||||
// Do it before the next step, as the next step stores references to the face indices in the hash tables and removing a facet
|
||||
// will break the references.
|
||||
for (int i = 0; i < stl->stats.number_of_facets;) {
|
||||
stl_facet &facet = stl->facet_start[i];
|
||||
if (facet.vertex[0] == facet.vertex[1] || facet.vertex[1] == facet.vertex[2] || facet.vertex[0] == facet.vertex[2]) {
|
||||
// Remove the degenerate facet.
|
||||
facet = stl->facet_start[--stl->stats.number_of_facets];
|
||||
stl->stats.facets_removed += 1;
|
||||
stl->stats.degenerate_facets += 1;
|
||||
} else
|
||||
++ i;
|
||||
}
|
||||
|
||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||
facet = stl->facet_start[i];
|
||||
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
|
||||
if (facet.vertex[0] == facet.vertex[1] ||
|
||||
facet.vertex[1] == facet.vertex[2] ||
|
||||
facet.vertex[0] == facet.vertex[2]) {
|
||||
stl->stats.degenerate_facets += 1;
|
||||
stl_remove_facet(stl, i);
|
||||
-- i;
|
||||
continue;
|
||||
}
|
||||
for(j = 0; j < 3; j++) {
|
||||
edge.facet_number = i;
|
||||
// Connect neighbor edges.
|
||||
stl_initialize_facet_check_exact(stl);
|
||||
for (int i = 0; i < stl->stats.number_of_facets; i++) {
|
||||
const stl_facet &facet = stl->facet_start[i];
|
||||
for (int j = 0; j < 3; j++) {
|
||||
stl_hash_edge edge;
|
||||
edge.facet_number = i;
|
||||
edge.which_edge = j;
|
||||
stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
|
||||
insert_hash_edge(stl, edge, stl_record_neighbors);
|
||||
|
|
@ -109,9 +107,7 @@ stl_check_facets_exact(stl_file *stl) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
|
||||
stl_vertex *a, stl_vertex *b) {
|
||||
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b) {
|
||||
|
||||
if (stl->error) return;
|
||||
|
||||
|
|
@ -333,7 +329,9 @@ static void stl_free_edges(stl_file *stl)
|
|||
}
|
||||
}
|
||||
free(stl->heads);
|
||||
stl->heads = nullptr;
|
||||
free(stl->tail);
|
||||
stl->tail = nullptr;
|
||||
}
|
||||
|
||||
static void stl_initialize_facet_check_nearby(stl_file *stl)
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
FILE *fp;
|
||||
stl_facet *facet_start;
|
||||
stl_edge *edge_start;
|
||||
stl_hash_edge **heads;
|
||||
stl_hash_edge *tail;
|
||||
int M;
|
||||
|
|
@ -142,7 +141,6 @@ typedef struct {
|
|||
extern void stl_open(stl_file *stl, const char *file);
|
||||
extern void stl_close(stl_file *stl);
|
||||
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
|
||||
extern void stl_print_edges(stl_file *stl, FILE *file);
|
||||
extern void stl_print_neighbors(stl_file *stl, char *file);
|
||||
extern void stl_put_little_int(FILE *fp, int value_in);
|
||||
extern void stl_put_little_float(FILE *fp, float value_in);
|
||||
|
|
|
|||
|
|
@ -33,24 +33,6 @@
|
|||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
void
|
||||
stl_print_edges(stl_file *stl, FILE *file) {
|
||||
int i;
|
||||
int edges_allocated;
|
||||
|
||||
if (stl->error) return;
|
||||
|
||||
edges_allocated = stl->stats.number_of_facets * 3;
|
||||
for(i = 0; i < edges_allocated; i++) {
|
||||
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
|
||||
stl->edge_start[i].facet_number,
|
||||
stl->edge_start[i].p1(0), stl->edge_start[i].p1(1),
|
||||
stl->edge_start[i].p1(2), stl->edge_start[i].p2(0),
|
||||
stl->edge_start[i].p2(1), stl->edge_start[i].p2(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
stl_stats_out(stl_file *stl, FILE *file, char *input_file) {
|
||||
if (stl->error) return;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ endif()
|
|||
target_include_directories(ClipperBackend INTERFACE ${Boost_INCLUDE_DIRS} )
|
||||
target_sources(ClipperBackend INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geometries.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/clipper_polygon.hpp
|
||||
${SRC_DIR}/libnest2d/utils/boost_alg.hpp )
|
||||
|
||||
target_compile_definitions(ClipperBackend INTERFACE LIBNEST2D_BACKEND_CLIPPER)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef CLIPPER_POLYGON_HPP
|
||||
#define CLIPPER_POLYGON_HPP
|
||||
|
||||
#include <clipper.hpp>
|
||||
|
||||
namespace ClipperLib {
|
||||
|
||||
struct Polygon {
|
||||
Path Contour;
|
||||
Paths Holes;
|
||||
|
||||
inline Polygon() = default;
|
||||
|
||||
inline explicit Polygon(const Path& cont): Contour(cont) {}
|
||||
inline explicit Polygon(const Paths& holes):
|
||||
Holes(holes) {}
|
||||
inline Polygon(const Path& cont, const Paths& holes):
|
||||
Contour(cont), Holes(holes) {}
|
||||
|
||||
inline explicit Polygon(Path&& cont): Contour(std::move(cont)) {}
|
||||
inline explicit Polygon(Paths&& holes): Holes(std::move(holes)) {}
|
||||
inline Polygon(Path&& cont, Paths&& holes):
|
||||
Contour(std::move(cont)), Holes(std::move(holes)) {}
|
||||
};
|
||||
|
||||
inline IntPoint& operator +=(IntPoint& p, const IntPoint& pa ) {
|
||||
// This could be done with SIMD
|
||||
p.X += pa.X;
|
||||
p.Y += pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline IntPoint operator+(const IntPoint& p1, const IntPoint& p2) {
|
||||
IntPoint ret = p1;
|
||||
ret += p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline IntPoint& operator -=(IntPoint& p, const IntPoint& pa ) {
|
||||
p.X -= pa.X;
|
||||
p.Y -= pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline IntPoint operator -(IntPoint& p ) {
|
||||
IntPoint ret = p;
|
||||
ret.X = -ret.X;
|
||||
ret.Y = -ret.Y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline IntPoint operator-(const IntPoint& p1, const IntPoint& p2) {
|
||||
IntPoint ret = p1;
|
||||
ret -= p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline IntPoint& operator *=(IntPoint& p, const IntPoint& pa ) {
|
||||
p.X *= pa.X;
|
||||
p.Y *= pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline IntPoint operator*(const IntPoint& p1, const IntPoint& p2) {
|
||||
IntPoint ret = p1;
|
||||
ret *= p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // CLIPPER_POLYGON_HPP
|
||||
|
|
@ -10,84 +10,15 @@
|
|||
#include <libnest2d/geometry_traits.hpp>
|
||||
#include <libnest2d/geometry_traits_nfp.hpp>
|
||||
|
||||
#include <clipper.hpp>
|
||||
|
||||
namespace ClipperLib {
|
||||
using PointImpl = IntPoint;
|
||||
using PathImpl = Path;
|
||||
using HoleStore = std::vector<PathImpl>;
|
||||
|
||||
struct PolygonImpl {
|
||||
PathImpl Contour;
|
||||
HoleStore Holes;
|
||||
|
||||
inline PolygonImpl() = default;
|
||||
|
||||
inline explicit PolygonImpl(const PathImpl& cont): Contour(cont) {}
|
||||
inline explicit PolygonImpl(const HoleStore& holes):
|
||||
Holes(holes) {}
|
||||
inline PolygonImpl(const Path& cont, const HoleStore& holes):
|
||||
Contour(cont), Holes(holes) {}
|
||||
|
||||
inline explicit PolygonImpl(PathImpl&& cont): Contour(std::move(cont)) {}
|
||||
inline explicit PolygonImpl(HoleStore&& holes): Holes(std::move(holes)) {}
|
||||
inline PolygonImpl(Path&& cont, HoleStore&& holes):
|
||||
Contour(std::move(cont)), Holes(std::move(holes)) {}
|
||||
};
|
||||
|
||||
inline PointImpl& operator +=(PointImpl& p, const PointImpl& pa ) {
|
||||
// This could be done with SIMD
|
||||
p.X += pa.X;
|
||||
p.Y += pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline PointImpl operator+(const PointImpl& p1, const PointImpl& p2) {
|
||||
PointImpl ret = p1;
|
||||
ret += p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline PointImpl& operator -=(PointImpl& p, const PointImpl& pa ) {
|
||||
p.X -= pa.X;
|
||||
p.Y -= pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline PointImpl operator -(PointImpl& p ) {
|
||||
PointImpl ret = p;
|
||||
ret.X = -ret.X;
|
||||
ret.Y = -ret.Y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline PointImpl operator-(const PointImpl& p1, const PointImpl& p2) {
|
||||
PointImpl ret = p1;
|
||||
ret -= p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline PointImpl& operator *=(PointImpl& p, const PointImpl& pa ) {
|
||||
p.X *= pa.X;
|
||||
p.Y *= pa.Y;
|
||||
return p;
|
||||
}
|
||||
|
||||
inline PointImpl operator*(const PointImpl& p1, const PointImpl& p2) {
|
||||
PointImpl ret = p1;
|
||||
ret *= p2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
#include "clipper_polygon.hpp"
|
||||
|
||||
namespace libnest2d {
|
||||
|
||||
// Aliases for convinience
|
||||
using ClipperLib::PointImpl;
|
||||
using ClipperLib::PathImpl;
|
||||
using ClipperLib::PolygonImpl;
|
||||
using ClipperLib::HoleStore;
|
||||
using PointImpl = ClipperLib::IntPoint;
|
||||
using PathImpl = ClipperLib::Path;
|
||||
using HoleStore = ClipperLib::Paths;
|
||||
using PolygonImpl = ClipperLib::Polygon;
|
||||
|
||||
// Type of coordinate units used by Clipper
|
||||
template<> struct CoordType<PointImpl> {
|
||||
|
|
@ -158,33 +89,24 @@ template<> inline TCoord<PointImpl>& y(PointImpl& p)
|
|||
#define DISABLE_BOOST_AREA
|
||||
|
||||
namespace _smartarea {
|
||||
|
||||
template<Orientation o>
|
||||
inline double area(const PolygonImpl& /*sh*/) {
|
||||
return std::nan("");
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double area<Orientation::CLOCKWISE>(const PolygonImpl& sh) {
|
||||
double a = 0;
|
||||
|
||||
std::for_each(sh.Holes.begin(), sh.Holes.end(), [&a](const PathImpl& h)
|
||||
{
|
||||
a -= ClipperLib::Area(h);
|
||||
inline double area<Orientation::COUNTER_CLOCKWISE>(const PolygonImpl& sh) {
|
||||
return std::accumulate(sh.Holes.begin(), sh.Holes.end(),
|
||||
ClipperLib::Area(sh.Contour),
|
||||
[](double a, const ClipperLib::Path& pt){
|
||||
return a + ClipperLib::Area(pt);
|
||||
});
|
||||
|
||||
return -ClipperLib::Area(sh.Contour) + a;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double area<Orientation::COUNTER_CLOCKWISE>(const PolygonImpl& sh) {
|
||||
double a = 0;
|
||||
|
||||
std::for_each(sh.Holes.begin(), sh.Holes.end(), [&a](const PathImpl& h)
|
||||
{
|
||||
a += ClipperLib::Area(h);
|
||||
});
|
||||
|
||||
return ClipperLib::Area(sh.Contour) + a;
|
||||
inline double area<Orientation::CLOCKWISE>(const PolygonImpl& sh) {
|
||||
return -area<Orientation::COUNTER_CLOCKWISE>(sh);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -228,9 +150,10 @@ template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
|
|||
// but throwing would be an overkill. Instead, we should warn the
|
||||
// caller about the inability to create correct geometries
|
||||
if(!found_the_contour) {
|
||||
sh.Contour = r;
|
||||
sh.Contour = std::move(r);
|
||||
ClipperLib::ReversePath(sh.Contour);
|
||||
sh.Contour.push_back(sh.Contour.front());
|
||||
auto front_p = sh.Contour.front();
|
||||
sh.Contour.emplace_back(std::move(front_p));
|
||||
found_the_contour = true;
|
||||
} else {
|
||||
dout() << "Warning: offsetting result is invalid!";
|
||||
|
|
@ -240,9 +163,10 @@ template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
|
|||
// TODO If there are multiple contours we can't be sure which hole
|
||||
// belongs to the first contour. (But in this case the situation is
|
||||
// bad enough to let it go...)
|
||||
sh.Holes.push_back(r);
|
||||
sh.Holes.emplace_back(std::move(r));
|
||||
ClipperLib::ReversePath(sh.Holes.back());
|
||||
sh.Holes.back().push_back(sh.Holes.back().front());
|
||||
auto front_p = sh.Holes.back().front();
|
||||
sh.Holes.back().emplace_back(std::move(front_p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -390,34 +314,53 @@ inline void rotate(PolygonImpl& sh, const Radians& rads)
|
|||
} // namespace shapelike
|
||||
|
||||
#define DISABLE_BOOST_NFP_MERGE
|
||||
inline std::vector<PolygonImpl> _merge(ClipperLib::Clipper& clipper) {
|
||||
inline std::vector<PolygonImpl> clipper_execute(
|
||||
ClipperLib::Clipper& clipper,
|
||||
ClipperLib::ClipType clipType,
|
||||
ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
|
||||
ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd)
|
||||
{
|
||||
shapelike::Shapes<PolygonImpl> retv;
|
||||
|
||||
ClipperLib::PolyTree result;
|
||||
clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftNegative);
|
||||
clipper.Execute(clipType, result, subjFillType, clipFillType);
|
||||
|
||||
retv.reserve(static_cast<size_t>(result.Total()));
|
||||
|
||||
std::function<void(ClipperLib::PolyNode*, PolygonImpl&)> processHole;
|
||||
|
||||
auto processPoly = [&retv, &processHole](ClipperLib::PolyNode *pptr) {
|
||||
PolygonImpl poly(pptr->Contour);
|
||||
poly.Contour.push_back(poly.Contour.front());
|
||||
PolygonImpl poly;
|
||||
poly.Contour.swap(pptr->Contour);
|
||||
|
||||
assert(!pptr->IsHole());
|
||||
|
||||
if(pptr->IsOpen()) {
|
||||
auto front_p = poly.Contour.front();
|
||||
poly.Contour.emplace_back(front_p);
|
||||
}
|
||||
|
||||
for(auto h : pptr->Childs) { processHole(h, poly); }
|
||||
retv.push_back(poly);
|
||||
};
|
||||
|
||||
processHole = [&processPoly](ClipperLib::PolyNode *pptr, PolygonImpl& poly)
|
||||
{
|
||||
poly.Holes.push_back(pptr->Contour);
|
||||
poly.Holes.back().push_back(poly.Holes.back().front());
|
||||
poly.Holes.emplace_back(std::move(pptr->Contour));
|
||||
|
||||
assert(pptr->IsHole());
|
||||
|
||||
if(pptr->IsOpen()) {
|
||||
auto front_p = poly.Holes.back().front();
|
||||
poly.Holes.back().emplace_back(front_p);
|
||||
}
|
||||
|
||||
for(auto c : pptr->Childs) processPoly(c);
|
||||
};
|
||||
|
||||
auto traverse = [&processPoly] (ClipperLib::PolyNode *node)
|
||||
{
|
||||
for(auto ch : node->Childs) {
|
||||
processPoly(ch);
|
||||
}
|
||||
for(auto ch : node->Childs) processPoly(ch);
|
||||
};
|
||||
|
||||
traverse(&result);
|
||||
|
|
@ -438,14 +381,13 @@ merge(const std::vector<PolygonImpl>& shapes)
|
|||
for(auto& path : shapes) {
|
||||
valid &= clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
|
||||
|
||||
for(auto& hole : path.Holes) {
|
||||
valid &= clipper.AddPath(hole, ClipperLib::ptSubject, closed);
|
||||
}
|
||||
for(auto& h : path.Holes)
|
||||
valid &= clipper.AddPath(h, ClipperLib::ptSubject, closed);
|
||||
}
|
||||
|
||||
if(!valid) throw GeometryException(GeomErr::MERGE);
|
||||
|
||||
return _merge(clipper);
|
||||
return clipper_execute(clipper, ClipperLib::ctUnion, ClipperLib::pftNegative);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ private:
|
|||
|
||||
for(size_t i = 0; i < pckgrp.size(); i++) {
|
||||
auto items = pckgrp[i];
|
||||
pg.push_back({});
|
||||
pg.emplace_back();
|
||||
pg[i].reserve(items.size());
|
||||
|
||||
for(Item& itemA : items) {
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ template<class RawShape> class EdgeCache {
|
|||
while(next != endit) {
|
||||
contour_.emap.emplace_back(*(first++), *(next++));
|
||||
contour_.full_distance += contour_.emap.back().length();
|
||||
contour_.distances.push_back(contour_.full_distance);
|
||||
contour_.distances.emplace_back(contour_.full_distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,10 +276,10 @@ template<class RawShape> class EdgeCache {
|
|||
while(next != endit) {
|
||||
hc.emap.emplace_back(*(first++), *(next++));
|
||||
hc.full_distance += hc.emap.back().length();
|
||||
hc.distances.push_back(hc.full_distance);
|
||||
hc.distances.emplace_back(hc.full_distance);
|
||||
}
|
||||
|
||||
holes_.push_back(hc);
|
||||
holes_.emplace_back(std::move(hc));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
bool pack(Item& item, const Range& rem = Range()) {
|
||||
auto&& r = static_cast<Subclass*>(this)->trypack(item, rem);
|
||||
if(r) {
|
||||
items_.push_back(*(r.item_ptr_));
|
||||
items_.emplace_back(*(r.item_ptr_));
|
||||
farea_valid_ = false;
|
||||
}
|
||||
return r;
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
if(r) {
|
||||
r.item_ptr_->translation(r.move_);
|
||||
r.item_ptr_->rotation(r.rot_);
|
||||
items_.push_back(*(r.item_ptr_));
|
||||
items_.emplace_back(*(r.item_ptr_));
|
||||
farea_valid_ = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ public:
|
|||
addBin();
|
||||
ItemList& not_packed = not_packeds[b];
|
||||
for(unsigned idx = b; idx < store_.size(); idx+=bincount_guess) {
|
||||
not_packed.push_back(store_[idx]);
|
||||
not_packed.emplace_back(store_[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ template<> inline std::string serialize<libnest2d::Formats::SVG>(
|
|||
auto& v = *it;
|
||||
hf.emplace_back(getX(v)*scale, getY(v)*scale);
|
||||
};
|
||||
holes.push_back(hf);
|
||||
holes.emplace_back(std::move(hf));
|
||||
}
|
||||
|
||||
Polygonf poly;
|
||||
|
|
|
|||
|
|
@ -2,36 +2,10 @@
|
|||
#define PRINTER_PARTS_H
|
||||
|
||||
#include <vector>
|
||||
#include <clipper.hpp>
|
||||
|
||||
#ifndef CLIPPER_BACKEND_HPP
|
||||
namespace ClipperLib {
|
||||
using PointImpl = IntPoint;
|
||||
using PathImpl = Path;
|
||||
using HoleStore = std::vector<PathImpl>;
|
||||
|
||||
struct PolygonImpl {
|
||||
PathImpl Contour;
|
||||
HoleStore Holes;
|
||||
|
||||
inline PolygonImpl() {}
|
||||
|
||||
inline explicit PolygonImpl(const PathImpl& cont): Contour(cont) {}
|
||||
inline explicit PolygonImpl(const HoleStore& holes):
|
||||
Holes(holes) {}
|
||||
inline PolygonImpl(const Path& cont, const HoleStore& holes):
|
||||
Contour(cont), Holes(holes) {}
|
||||
|
||||
inline explicit PolygonImpl(PathImpl&& cont): Contour(std::move(cont)) {}
|
||||
inline explicit PolygonImpl(HoleStore&& holes): Holes(std::move(holes)) {}
|
||||
inline PolygonImpl(Path&& cont, HoleStore&& holes):
|
||||
Contour(std::move(cont)), Holes(std::move(holes)) {}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
using TestData = std::vector<ClipperLib::Path>;
|
||||
using TestDataEx = std::vector<ClipperLib::PolygonImpl>;
|
||||
using TestDataEx = std::vector<ClipperLib::Polygon>;
|
||||
|
||||
extern const TestData PRINTER_PART_POLYGONS;
|
||||
extern const TestData STEGOSAUR_POLYGONS;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ add_library(libslic3r STATIC
|
|||
utils.cpp
|
||||
Utils.hpp
|
||||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
SLA/SLABoilerPlate.hpp
|
||||
SLA/SLABasePool.hpp
|
||||
SLA/SLABasePool.cpp
|
||||
|
|
@ -177,8 +179,8 @@ if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
|||
add_precompiled_header(libslic3r pchheader.hpp FORCEINCLUDE)
|
||||
endif ()
|
||||
|
||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB ${PNG_DEFINITIONS})
|
||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB)
|
||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(libslic3r
|
||||
libnest2d
|
||||
admesh
|
||||
|
|
@ -188,7 +190,6 @@ target_link_libraries(libslic3r
|
|||
nowide
|
||||
${EXPAT_LIBRARIES}
|
||||
${GLEW_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
glu-libtess
|
||||
polypartition
|
||||
poly2tri
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input)
|
|||
{
|
||||
Polygon retval;
|
||||
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
|
||||
retval.points.push_back(Point( (*pit).X, (*pit).Y ));
|
||||
retval.points.emplace_back(pit->X, pit->Y);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input)
|
|||
{
|
||||
Polyline retval;
|
||||
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
|
||||
retval.points.push_back(Point( (*pit).X, (*pit).Y ));
|
||||
retval.points.emplace_back(pit->X, pit->Y);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ Slic3r::Polygons ClipperPaths_to_Slic3rPolygons(const ClipperLib::Paths &input)
|
|||
Slic3r::Polygons retval;
|
||||
retval.reserve(input.size());
|
||||
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
|
||||
retval.push_back(ClipperPath_to_Slic3rPolygon(*it));
|
||||
retval.emplace_back(ClipperPath_to_Slic3rPolygon(*it));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input
|
|||
Slic3r::Polylines retval;
|
||||
retval.reserve(input.size());
|
||||
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
|
||||
retval.push_back(ClipperPath_to_Slic3rPolyline(*it));
|
||||
retval.emplace_back(ClipperPath_to_Slic3rPolyline(*it));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
|
|||
{
|
||||
ClipperLib::Path retval;
|
||||
for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
|
||||
retval.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) ));
|
||||
retval.emplace_back((*pit)(0), (*pit)(1));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input)
|
|||
ClipperLib::Path output;
|
||||
output.reserve(input.points.size());
|
||||
for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit)
|
||||
output.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) ));
|
||||
output.emplace_back((*pit)(0), (*pit)(1));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polygons &input)
|
|||
{
|
||||
ClipperLib::Paths retval;
|
||||
for (Polygons::const_iterator it = input.begin(); it != input.end(); ++it)
|
||||
retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it));
|
||||
retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input)
|
|||
{
|
||||
ClipperLib::Paths retval;
|
||||
for (Polylines::const_iterator it = input.begin(); it != input.end(); ++it)
|
||||
retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it));
|
||||
retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType
|
|||
ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
ClipperLib::Paths paths;
|
||||
paths.push_back(std::move(input));
|
||||
paths.emplace_back(std::move(input));
|
||||
return _offset(std::move(paths), endType, delta, joinType, miterLimit);
|
||||
}
|
||||
|
||||
|
|
@ -585,7 +585,7 @@ Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, co
|
|||
Polylines polylines;
|
||||
polylines.reserve(subject.size());
|
||||
for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon)
|
||||
polylines.push_back(*polygon); // implicit call to split_at_first_point()
|
||||
polylines.emplace_back(polygon->operator Polyline()); // implicit call to split_at_first_point()
|
||||
|
||||
// perform clipping
|
||||
Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_);
|
||||
|
|
@ -643,7 +643,7 @@ _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons
|
|||
// convert Polylines to Lines
|
||||
Lines retval;
|
||||
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline)
|
||||
retval.push_back(*polyline);
|
||||
retval.emplace_back(polyline->operator Line());
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -673,7 +673,7 @@ void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
|
|||
ordering_points.reserve(nodes.size());
|
||||
for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
Point p((*it)->Contour.front().X, (*it)->Contour.front().Y);
|
||||
ordering_points.push_back(p);
|
||||
ordering_points.emplace_back(p);
|
||||
}
|
||||
|
||||
// perform the ordering
|
||||
|
|
@ -684,7 +684,7 @@ void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
|
|||
for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) {
|
||||
// traverse the next depth
|
||||
traverse_pt((*it)->Childs, retval);
|
||||
retval->push_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
|
||||
retval->emplace_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
|
||||
if ((*it)->IsHole()) retval->back().reverse(); // ccw
|
||||
}
|
||||
}
|
||||
|
|
@ -791,8 +791,8 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons)
|
|||
Polygons out;
|
||||
out.reserve(polytree.ChildCount());
|
||||
for (int i = 0; i < polytree.ChildCount(); ++i)
|
||||
out.push_back(ClipperPath_to_Slic3rPolygon(polytree.Childs[i]->Contour));
|
||||
out.emplace_back(ClipperPath_to_Slic3rPolygon(polytree.Childs[i]->Contour));
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ namespace Slic3r {
|
|||
|
||||
//-----------------------------------------------------------
|
||||
// legacy code from Clipper documentation
|
||||
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons);
|
||||
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
|
||||
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons *expolygons);
|
||||
Slic3r::ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree);
|
||||
//-----------------------------------------------------------
|
||||
|
||||
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input);
|
||||
|
|
@ -228,4 +228,4 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons);
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ struct AMFParserContext
|
|||
bool mirrory_set;
|
||||
float mirrorz;
|
||||
bool mirrorz_set;
|
||||
|
||||
bool anything_set() const { return deltax_set || deltay_set || deltaz_set ||
|
||||
rx_set || ry_set || rz_set ||
|
||||
scalex_set || scaley_set || scalez_set ||
|
||||
mirrorx_set || mirrory_set || mirrorz_set; }
|
||||
};
|
||||
|
||||
struct Object {
|
||||
|
|
@ -644,11 +649,7 @@ void AMFParserContext::endDocument()
|
|||
continue;
|
||||
}
|
||||
for (const Instance &instance : object.second.instances)
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
#else
|
||||
if (instance.deltax_set && instance.deltay_set) {
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
if (instance.anything_set()) {
|
||||
ModelInstance *mi = m_model.objects[object.second.idx]->add_instance();
|
||||
mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0));
|
||||
mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0));
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,15 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||
}
|
||||
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
|
||||
_write(file, m_writer.postamble());
|
||||
|
||||
// adds tags for time estimators
|
||||
if (print.config().remaining_times.value)
|
||||
{
|
||||
_writeln(file, GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag);
|
||||
if (m_silent_time_estimator_enabled)
|
||||
_writeln(file, GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag);
|
||||
}
|
||||
|
||||
print.throw_if_canceled();
|
||||
|
||||
// calculates estimated printing time
|
||||
|
|
@ -2408,6 +2417,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
{
|
||||
std::string gcode;
|
||||
|
||||
if (is_bridge(path.role()))
|
||||
description += " (bridge)";
|
||||
|
||||
// go to first point of extrusion path
|
||||
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
|
||||
gcode += this->travel_to(
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||
GCodePreviewData::Range volumetric_rate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
|
|
@ -776,6 +776,9 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||
preview_data.ranges.width.update_from(width_range);
|
||||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
||||
|
||||
// we need to sort the layers by their z as they can be shuffled in case of sequential prints
|
||||
std::sort(preview_data.extrusion.layers.begin(), preview_data.extrusion.layers.end(), [](const GCodePreviewData::Extrusion::Layer& l1, const GCodePreviewData::Extrusion::Layer& l2)->bool { return l1.z < l2.z; });
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
|
|
@ -807,7 +810,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
|
|||
GCodePreviewData::Range feedrate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
|
|
@ -855,6 +858,11 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
|
|||
preview_data.ranges.height.update_from(height_range);
|
||||
preview_data.ranges.width.update_from(width_range);
|
||||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
|
||||
// we need to sort the polylines by their min z as they can be shuffled in case of sequential prints
|
||||
std::sort(preview_data.travel.polylines.begin(), preview_data.travel.polylines.end(),
|
||||
[](const GCodePreviewData::Travel::Polyline& p1, const GCodePreviewData::Travel::Polyline& p2)->bool
|
||||
{ return unscale<double>(p1.polyline.bounding_box().min(2)) < unscale<double>(p2.polyline.bounding_box().min(2)); });
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
|
|
@ -864,7 +872,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
|
|||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)retraction_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : retraction_moves->second)
|
||||
|
|
@ -877,6 +885,11 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
|
|||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
|
||||
// we need to sort the positions by their z as they can be shuffled in case of sequential prints
|
||||
std::sort(preview_data.retraction.positions.begin(), preview_data.retraction.positions.end(),
|
||||
[](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2)->bool
|
||||
{ return unscale<double>(p1.position(2)) < unscale<double>(p2.position(2)); });
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
|
|
@ -886,7 +899,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
|
|||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)unretraction_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : unretraction_moves->second)
|
||||
|
|
@ -899,6 +912,11 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
|
|||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
|
||||
// we need to sort the positions by their z as they can be shuffled in case of sequential prints
|
||||
std::sort(preview_data.unretraction.positions.begin(), preview_data.unretraction.positions.end(),
|
||||
[](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2)->bool
|
||||
{ return unscale<double>(p1.position(2)) < unscale<double>(p2.position(2)); });
|
||||
}
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
// https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
|
||||
// This routine appends the given argument to a command line such that CommandLineToArgvW will return the argument string unchanged.
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ namespace Slic3r {
|
|||
|
||||
const std::string GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag = "; NORMAL_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag = "; SILENT_FIRST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
|
||||
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
|
||||
: _mode(mode)
|
||||
|
|
@ -306,9 +308,17 @@ namespace Slic3r {
|
|||
sprintf(time_line, time_mask.c_str(), "0", _get_time_minutes(_time).c_str());
|
||||
gcode_line = time_line;
|
||||
}
|
||||
// replaces placeholders for final line M73 with the real lines
|
||||
else if (((_mode == Normal) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag)) ||
|
||||
((_mode == Silent) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag)))
|
||||
{
|
||||
sprintf(time_line, time_mask.c_str(), "100", "0");
|
||||
gcode_line = time_line;
|
||||
}
|
||||
else
|
||||
gcode_line += "\n";
|
||||
|
||||
|
||||
// add remaining time lines where needed
|
||||
_parser.parse_line(gcode_line,
|
||||
[this, &it_line_id, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ namespace Slic3r {
|
|||
public:
|
||||
static const std::string Normal_First_M73_Output_Placeholder_Tag;
|
||||
static const std::string Silent_First_M73_Output_Placeholder_Tag;
|
||||
static const std::string Normal_Last_M73_Output_Placeholder_Tag;
|
||||
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
|
||||
|
||||
enum EMode : unsigned char
|
||||
{
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ public:
|
|||
|
||||
const Vec3d& get_mirror() const { return m_mirror; }
|
||||
double get_mirror(Axis axis) const { return m_mirror(axis); }
|
||||
bool is_left_handed() const { return m_mirror.x() * m_mirror.y() * m_mirror.z() < 0.; }
|
||||
|
||||
void set_mirror(const Vec3d& mirror);
|
||||
void set_mirror(Axis axis, double mirror);
|
||||
|
|
|
|||
|
|
@ -258,13 +258,18 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|||
#ifdef SLIC3R_DEBUG
|
||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||
#endif
|
||||
if (bd.detect_angle(Geometry::deg2rad(this->region()->config().bridge_angle.value))) {
|
||||
double custom_angle = Geometry::deg2rad(this->region()->config().bridge_angle.value);
|
||||
if (bd.detect_angle(custom_angle)) {
|
||||
bridges[idx_last].bridge_angle = bd.angle;
|
||||
if (this->layer()->object()->config().support_material) {
|
||||
polygons_append(this->bridged, bd.coverage());
|
||||
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
||||
}
|
||||
}
|
||||
} else if (custom_angle > 0) {
|
||||
// Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in
|
||||
// using a bridging flow, therefore it makes sense to respect the custom bridging direction.
|
||||
bridges[idx_last].bridge_angle = custom_angle;
|
||||
}
|
||||
// without safety offset, artifacts are generated (GH #2494)
|
||||
surfaces_append(bottom, union_ex(grown, true), bridges[idx_last]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,132 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// An std compatible random access iterator which uses indices to the source
|
||||
/// vector thus resistant to invalidation caused by relocations. It also "knows"
|
||||
/// its container. No comparison is neccesary to the container "end()" iterator.
|
||||
/// The template can be instantiated with a different value type than that of
|
||||
/// the container's but the types must be compatible. E.g. a base class of the
|
||||
/// contained objects is compatible.
|
||||
///
|
||||
/// For a constant iterator, one can instantiate this template with a value
|
||||
/// type preceded with 'const'.
|
||||
template<class Vector, // The container type, must be random access...
|
||||
class Value = typename Vector::value_type // The value type
|
||||
>
|
||||
class IndexBasedIterator {
|
||||
static const size_t NONE = size_t(-1);
|
||||
|
||||
std::reference_wrapper<Vector> m_index_ref;
|
||||
size_t m_idx = NONE;
|
||||
public:
|
||||
|
||||
using value_type = Value;
|
||||
using pointer = Value *;
|
||||
using reference = Value &;
|
||||
using difference_type = long;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
inline explicit
|
||||
IndexBasedIterator(Vector& index, size_t idx):
|
||||
m_index_ref(index), m_idx(idx) {}
|
||||
|
||||
// Post increment
|
||||
inline IndexBasedIterator operator++(int) {
|
||||
IndexBasedIterator cpy(*this); ++m_idx; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator--(int) {
|
||||
IndexBasedIterator cpy(*this); --m_idx; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator++() {
|
||||
++m_idx; return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator--() {
|
||||
--m_idx; return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator+=(difference_type l) {
|
||||
m_idx += size_t(l); return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator+(difference_type l) {
|
||||
auto cpy = *this; cpy += l; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator-=(difference_type l) {
|
||||
m_idx -= size_t(l); return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator-(difference_type l) {
|
||||
auto cpy = *this; cpy -= l; return cpy;
|
||||
}
|
||||
|
||||
operator difference_type() { return difference_type(m_idx); }
|
||||
|
||||
/// Tesing the end of the container... this is not possible with std
|
||||
/// iterators.
|
||||
inline bool is_end() const { return m_idx >= m_index_ref.get().size();}
|
||||
|
||||
inline Value & operator*() const {
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
inline Value * operator->() const {
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return &m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
/// If both iterators point past the container, they are equal...
|
||||
inline bool operator ==(const IndexBasedIterator& other) {
|
||||
size_t e = m_index_ref.get().size();
|
||||
return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e);
|
||||
}
|
||||
|
||||
inline bool operator !=(const IndexBasedIterator& other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <=(const IndexBasedIterator& other) {
|
||||
return (m_idx < other.m_idx) || (*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <(const IndexBasedIterator& other) {
|
||||
return m_idx < other.m_idx && (*this != other);
|
||||
}
|
||||
|
||||
inline bool operator >=(const IndexBasedIterator& other) {
|
||||
return m_idx > other.m_idx || *this == other;
|
||||
}
|
||||
|
||||
inline bool operator >(const IndexBasedIterator& other) {
|
||||
return m_idx > other.m_idx && *this != other;
|
||||
}
|
||||
};
|
||||
|
||||
/// A very simple range concept implementation with iterator-like objects.
|
||||
template<class It> class Range {
|
||||
It from, to;
|
||||
public:
|
||||
|
||||
// The class is ready for range based for loops.
|
||||
It begin() const { return from; }
|
||||
It end() const { return to; }
|
||||
|
||||
// The iterator type can be obtained this way.
|
||||
using Type = It;
|
||||
|
||||
Range() = default;
|
||||
Range(It &&b, It &&e):
|
||||
from(std::forward<It>(b)), to(std::forward<It>(e)) {}
|
||||
|
||||
// Some useful container-like methods...
|
||||
inline size_t size() const { return end() - begin(); }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MTUTILS_HPP
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ Model& Model::assign_copy(Model &&rhs)
|
|||
this->objects = std::move(rhs.objects);
|
||||
for (ModelObject *model_object : this->objects)
|
||||
model_object->set_model(this);
|
||||
rhs.objects.clear();
|
||||
rhs.objects.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -556,19 +556,9 @@ std::string Model::propose_export_file_name_and_path() const
|
|||
for (const ModelObject *model_object : this->objects)
|
||||
for (ModelInstance *model_instance : model_object->instances)
|
||||
if (model_instance->is_printable()) {
|
||||
input_file = model_object->input_file;
|
||||
if (! model_object->name.empty()) {
|
||||
if (input_file.empty())
|
||||
// model_object->input_file was empty, just use model_object->name
|
||||
input_file = model_object->name;
|
||||
else {
|
||||
// Replace file name in input_file with model_object->name, but keep the path and file extension.
|
||||
input_file = (boost::filesystem::path(model_object->name).parent_path().empty()) ?
|
||||
(boost::filesystem::path(input_file).parent_path() / model_object->name).make_preferred().string() :
|
||||
model_object->name;
|
||||
}
|
||||
}
|
||||
if (! input_file.empty())
|
||||
input_file = model_object->get_export_filename();
|
||||
|
||||
if (!input_file.empty())
|
||||
goto end;
|
||||
// Other instances will produce the same name, skip them.
|
||||
break;
|
||||
|
|
@ -651,7 +641,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
|
|||
for (ModelInstance *model_instance : this->instances)
|
||||
model_instance->set_model_object(this);
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ModelObject::assign_new_unique_ids_recursive()
|
||||
|
|
@ -970,8 +960,8 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance)
|
|||
}
|
||||
}
|
||||
}
|
||||
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
|
||||
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
|
||||
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
|
||||
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
|
||||
|
||||
Polygon hull;
|
||||
int n = (int)pts.size();
|
||||
|
|
@ -997,12 +987,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance)
|
|||
return hull;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void ModelObject::center_around_origin(bool include_modifiers)
|
||||
#else
|
||||
void ModelObject::center_around_origin()
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
// calculate the displacements needed to
|
||||
// center this object around the origin
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
BoundingBoxf3 bb = full_raw_mesh_bounding_box();
|
||||
BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
|
||||
#else
|
||||
BoundingBoxf3 bb;
|
||||
for (ModelVolume *v : this->volumes)
|
||||
|
|
@ -1183,8 +1177,9 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
else {
|
||||
TriangleMesh upper_mesh, lower_mesh;
|
||||
|
||||
// Transform the mesh by the combined transformation matrix
|
||||
volume->mesh.transform(instance_matrix * volume_matrix);
|
||||
// Transform the mesh by the combined transformation matrix.
|
||||
// Flip the triangles in case the composite transformation is left handed.
|
||||
volume->mesh.transform(instance_matrix * volume_matrix, true);
|
||||
|
||||
// Perform cut
|
||||
TriangleMeshSlicer tms(&volume->mesh);
|
||||
|
|
@ -1287,11 +1282,11 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||
|
||||
// XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed?
|
||||
ModelObject* new_object = m_model->add_object();
|
||||
new_object->name = this->name;
|
||||
new_object->config = this->config;
|
||||
new_object->instances.reserve(this->instances.size());
|
||||
for (const ModelInstance *model_instance : this->instances)
|
||||
new_object->add_instance(*model_instance);
|
||||
new_object->name = this->name;
|
||||
new_object->config = this->config;
|
||||
new_object->instances.reserve(this->instances.size());
|
||||
for (const ModelInstance *model_instance : this->instances)
|
||||
new_object->add_instance(*model_instance);
|
||||
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh));
|
||||
#if !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
new_vol->center_geometry();
|
||||
|
|
@ -1428,6 +1423,26 @@ void ModelObject::print_info() const
|
|||
cout << "volume = " << mesh.volume() << endl;
|
||||
}
|
||||
|
||||
std::string ModelObject::get_export_filename() const
|
||||
{
|
||||
std::string ret = input_file;
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
if (ret.empty())
|
||||
// input_file was empty, just use name
|
||||
ret = name;
|
||||
else
|
||||
{
|
||||
// Replace file name in input_file with name, but keep the path and file extension.
|
||||
ret = (boost::filesystem::path(name).parent_path().empty()) ?
|
||||
(boost::filesystem::path(ret).parent_path() / name).make_preferred().string() : name;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ModelVolume::set_material_id(t_model_material_id material_id)
|
||||
{
|
||||
m_material_id = material_id;
|
||||
|
|
@ -1463,9 +1478,9 @@ int ModelVolume::extruder_id() const
|
|||
|
||||
bool ModelVolume::is_splittable() const
|
||||
{
|
||||
// the call mesh.has_multiple_patches() is expensive, so cache the value to calculate it only once
|
||||
// the call mesh.is_splittable() is expensive, so cache the value to calculate it only once
|
||||
if (m_is_splittable == -1)
|
||||
m_is_splittable = (int)mesh.has_multiple_patches();
|
||||
m_is_splittable = (int)mesh.is_splittable();
|
||||
|
||||
return m_is_splittable == 1;
|
||||
}
|
||||
|
|
@ -1605,6 +1620,7 @@ void ModelVolume::rotate(double angle, Axis axis)
|
|||
case X: { rotate(angle, Vec3d::UnitX()); break; }
|
||||
case Y: { rotate(angle, Vec3d::UnitY()); break; }
|
||||
case Z: { rotate(angle, Vec3d::UnitZ()); break; }
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1621,6 +1637,7 @@ void ModelVolume::mirror(Axis axis)
|
|||
case X: { mirror(0) *= -1.0; break; }
|
||||
case Y: { mirror(1) *= -1.0; break; }
|
||||
case Z: { mirror(2) *= -1.0; break; }
|
||||
default: break;
|
||||
}
|
||||
set_mirror(mirror);
|
||||
}
|
||||
|
|
@ -1707,7 +1724,6 @@ bool model_object_list_extended(const Model &model_old, const Model &model_new)
|
|||
|
||||
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type)
|
||||
{
|
||||
bool modifiers_differ = false;
|
||||
size_t i_old, i_new;
|
||||
for (i_old = 0, i_new = 0; i_old < model_object_old.volumes.size() && i_new < model_object_new.volumes.size();) {
|
||||
const ModelVolume &mv_old = *model_object_old.volumes[i_old];
|
||||
|
|
|
|||
|
|
@ -236,7 +236,11 @@ public:
|
|||
// This method is used by the auto arrange function.
|
||||
Polygon convex_hull_2d(const Transform3d &trafo_instance);
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void center_around_origin(bool include_modifiers = true);
|
||||
#else
|
||||
void center_around_origin();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void ensure_on_bed();
|
||||
void translate_instances(const Vec3d& vector);
|
||||
void translate_instance(size_t instance_idx, const Vec3d& vector);
|
||||
|
|
@ -271,6 +275,8 @@ public:
|
|||
// Print object statistics to console.
|
||||
void print_info() const;
|
||||
|
||||
std::string get_export_filename() const;
|
||||
|
||||
protected:
|
||||
friend class Print;
|
||||
friend class SLAPrint;
|
||||
|
|
@ -390,6 +396,7 @@ public:
|
|||
|
||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||
|
||||
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
|
||||
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
|
||||
|
|
@ -494,6 +501,7 @@ public:
|
|||
|
||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||
|
||||
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
|
||||
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
|
||||
|
|
|
|||
|
|
@ -556,29 +556,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||
// TODO export the exact 2D projection. Cannot do it as libnest2d
|
||||
// does not support concave shapes (yet).
|
||||
ClipperLib::Path clpath;
|
||||
//WIP Vojtech's optimization of the calculation of the convex hull is not working correctly yet.
|
||||
#if 1
|
||||
{
|
||||
TriangleMesh rmesh = objptr->raw_mesh();
|
||||
|
||||
ModelInstance * finst = objptr->instances.front();
|
||||
|
||||
// Object instances should carry the same scaling and
|
||||
// x, y rotation that is why we use the first instance.
|
||||
// The next line will apply only the full mirroring and scaling
|
||||
rmesh.transform(finst->get_matrix(true, true, false, false));
|
||||
rmesh.rotate_x(float(finst->get_rotation()(X)));
|
||||
rmesh.rotate_y(float(finst->get_rotation()(Y)));
|
||||
|
||||
// TODO export the exact 2D projection. Cannot do it as libnest2d
|
||||
// does not support concave shapes (yet).
|
||||
auto p = rmesh.convex_hull();
|
||||
|
||||
p.make_clockwise();
|
||||
p.append(p.first_point());
|
||||
clpath = Slic3rMultiPoint_to_ClipperPath(p);
|
||||
}
|
||||
#else
|
||||
// Object instances should carry the same scaling and
|
||||
// x, y rotation that is why we use the first instance.
|
||||
{
|
||||
|
|
@ -593,11 +571,10 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||
p.append(p.first_point());
|
||||
clpath = Slic3rMultiPoint_to_ClipperPath(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
for(ModelInstance* objinst : objptr->instances) {
|
||||
if(objinst) {
|
||||
ClipperLib::PolygonImpl pn;
|
||||
ClipperLib::Polygon pn;
|
||||
pn.Contour = clpath;
|
||||
|
||||
// Efficient conversion to item.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "GCode/WipeTowerPrusaMM.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include "PrintExport.hpp"
|
||||
//#include "PrintExport.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Horizontal width of the brim that will be printed around each object on the first layer.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->mode = comSimple;
|
||||
def->default_value = new ConfigOptionFloat(0);
|
||||
|
||||
def = this->add("clip_multipart_objects", coBool);
|
||||
|
|
@ -1375,6 +1375,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("(minimum)");
|
||||
def->aliases = { "perimeter_offsets" };
|
||||
def->min = 0;
|
||||
def->max = 10000;
|
||||
def->default_value = new ConfigOptionInt(3);
|
||||
|
||||
def = this->add("post_process", coStrings);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "Rasterizer/Rasterizer.hpp"
|
||||
//#include <tbb/parallel_for.h>
|
||||
|
|
@ -42,8 +43,9 @@ template<FilePrinterFormat format>
|
|||
class FilePrinter {
|
||||
public:
|
||||
|
||||
// Draw an ExPolygon which is a polygon inside a slice on the specified layer.
|
||||
// Draw a polygon which is a polygon inside a slice on the specified layer.
|
||||
void draw_polygon(const ExPolygon& p, unsigned lyr);
|
||||
void draw_polygon(const ClipperLib::Polygon& p, unsigned lyr);
|
||||
|
||||
// Tell the printer how many layers should it consider.
|
||||
void layers(unsigned layernum);
|
||||
|
|
@ -71,7 +73,8 @@ public:
|
|||
void finish_layer();
|
||||
|
||||
// Save all the layers into the file (or dir) specified in the path argument
|
||||
void save(const std::string& path);
|
||||
// An optional project name can be added to be used for the layer file names
|
||||
void save(const std::string& path, const std::string& projectname = "");
|
||||
|
||||
// Save only the selected layer to the file specified in path argument.
|
||||
void save_layer(unsigned lyr, const std::string& path);
|
||||
|
|
@ -80,28 +83,35 @@ public:
|
|||
// Provokes static_assert in the right way.
|
||||
template<class T = void> struct VeryFalse { static const bool value = false; };
|
||||
|
||||
// This has to be explicitly implemented in the gui layer or a default zlib
|
||||
// based implementation is needed. I don't have time for that and I'm delegating
|
||||
// the implementation to the gui layer where the gui toolkit can cover this.
|
||||
// This can be explicitly implemented in the gui layer or the default Zipper
|
||||
// API in libslic3r with minz.
|
||||
template<class Fmt> class LayerWriter {
|
||||
public:
|
||||
|
||||
LayerWriter(const std::string& /*zipfile_path*/) {
|
||||
LayerWriter(const std::string& /*zipfile_path*/)
|
||||
{
|
||||
static_assert(VeryFalse<Fmt>::value,
|
||||
"No layer writer implementation provided!");
|
||||
}
|
||||
|
||||
// Should create a new file within the zip with the given filename. It
|
||||
// should also finish any previous entry.
|
||||
void next_entry(const std::string& /*fname*/) {}
|
||||
|
||||
std::string get_name() { return ""; }
|
||||
// Should create a new file within the archive and write the provided data.
|
||||
void binary_entry(const std::string& /*fname*/,
|
||||
const std::uint8_t* buf, size_t len);
|
||||
|
||||
// Test whether the object can still be used for writing.
|
||||
bool is_ok() { return false; }
|
||||
|
||||
template<class T> LayerWriter& operator<<(const T& /*arg*/) {
|
||||
// Write some data (text) into the current file (entry) within the archive.
|
||||
template<class T> LayerWriter& operator<<(T&& /*arg*/) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void close() {}
|
||||
// Flush the current entry into the archive.
|
||||
void finalize() {}
|
||||
};
|
||||
|
||||
// Implementation for PNG raster output
|
||||
|
|
@ -110,14 +120,14 @@ public:
|
|||
template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
||||
{
|
||||
struct Layer {
|
||||
Raster first;
|
||||
std::stringstream second;
|
||||
Raster raster;
|
||||
RawBytes rawbytes;
|
||||
|
||||
Layer() {}
|
||||
|
||||
Layer(const Layer&) = delete;
|
||||
Layer(Layer&& m):
|
||||
first(std::move(m.first))/*, second(std::move(m.second))*/ {}
|
||||
raster(std::move(m.raster)) {}
|
||||
};
|
||||
|
||||
// We will save the compressed PNG data into stringstreams which can be done
|
||||
|
|
@ -135,14 +145,11 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
|||
int m_cnt_fast_layers = 0;
|
||||
|
||||
std::string createIniContent(const std::string& projectname) {
|
||||
// double layer_height = m_layer_height;
|
||||
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
|
||||
auto expt_str = to_string(m_exp_time_s);
|
||||
auto expt_first_str = to_string(m_exp_time_first_s);
|
||||
// auto stepnum_str = to_string(static_cast<unsigned>(800*layer_height));
|
||||
auto layerh_str = to_string(m_layer_height);
|
||||
|
||||
const std::string cnt_fade_layers = to_string(m_cnt_fade_layers);
|
||||
|
|
@ -211,41 +218,48 @@ public:
|
|||
|
||||
inline void draw_polygon(const ExPolygon& p, unsigned lyr) {
|
||||
assert(lyr < m_layers_rst.size());
|
||||
m_layers_rst[lyr].first.draw(p);
|
||||
m_layers_rst[lyr].raster.draw(p);
|
||||
}
|
||||
|
||||
inline void draw_polygon(const ClipperLib::Polygon& p, unsigned lyr) {
|
||||
assert(lyr < m_layers_rst.size());
|
||||
m_layers_rst[lyr].raster.draw(p);
|
||||
}
|
||||
|
||||
inline void begin_layer(unsigned lyr) {
|
||||
if(m_layers_rst.size() <= lyr) m_layers_rst.resize(lyr+1);
|
||||
m_layers_rst[lyr].first.reset(m_res, m_pxdim, m_o);
|
||||
m_layers_rst[lyr].raster.reset(m_res, m_pxdim, m_o);
|
||||
}
|
||||
|
||||
inline void begin_layer() {
|
||||
m_layers_rst.emplace_back();
|
||||
m_layers_rst.front().first.reset(m_res, m_pxdim, m_o);
|
||||
m_layers_rst.front().raster.reset(m_res, m_pxdim, m_o);
|
||||
}
|
||||
|
||||
inline void finish_layer(unsigned lyr_id) {
|
||||
assert(lyr_id < m_layers_rst.size());
|
||||
m_layers_rst[lyr_id].first.save(m_layers_rst[lyr_id].second,
|
||||
Raster::Compression::PNG);
|
||||
m_layers_rst[lyr_id].first.reset();
|
||||
m_layers_rst[lyr_id].rawbytes =
|
||||
m_layers_rst[lyr_id].raster.save(Raster::Compression::PNG);
|
||||
m_layers_rst[lyr_id].raster.reset();
|
||||
}
|
||||
|
||||
inline void finish_layer() {
|
||||
if(!m_layers_rst.empty()) {
|
||||
m_layers_rst.back().first.save(m_layers_rst.back().second,
|
||||
Raster::Compression::PNG);
|
||||
m_layers_rst.back().first.reset();
|
||||
m_layers_rst.back().rawbytes =
|
||||
m_layers_rst.back().raster.save(Raster::Compression::PNG);
|
||||
m_layers_rst.back().raster.reset();
|
||||
}
|
||||
}
|
||||
|
||||
template<class LyrFmt>
|
||||
inline void save(const std::string& path) {
|
||||
inline void save(const std::string& fpath, const std::string& prjname = "")
|
||||
{
|
||||
try {
|
||||
LayerWriter<LyrFmt> writer(path);
|
||||
LayerWriter<LyrFmt> writer(fpath);
|
||||
if(!writer.is_ok()) return;
|
||||
|
||||
std::string project = writer.get_name();
|
||||
std::string project = prjname.empty()?
|
||||
boost::filesystem::path(fpath).stem().string() : prjname;
|
||||
|
||||
writer.next_entry("config.ini");
|
||||
if(!writer.is_ok()) return;
|
||||
|
|
@ -254,20 +268,19 @@ public:
|
|||
|
||||
for(unsigned i = 0; i < m_layers_rst.size() && writer.is_ok(); i++)
|
||||
{
|
||||
if(m_layers_rst[i].second.rdbuf()->in_avail() > 0) {
|
||||
if(m_layers_rst[i].rawbytes.size() > 0) {
|
||||
char lyrnum[6];
|
||||
std::sprintf(lyrnum, "%.5d", i);
|
||||
auto zfilename = project + lyrnum + ".png";
|
||||
writer.next_entry(zfilename);
|
||||
|
||||
if(!writer.is_ok()) break;
|
||||
|
||||
writer << m_layers_rst[i].second.str();
|
||||
// writer << m_layers_rst[i].second.rdbuf();
|
||||
// we can keep the date for later calls of this method
|
||||
//m_layers_rst[i].second.str("");
|
||||
writer.binary_entry(zfilename,
|
||||
m_layers_rst[i].rawbytes.data(),
|
||||
m_layers_rst[i].rawbytes.size());
|
||||
}
|
||||
}
|
||||
|
||||
writer.finalize();
|
||||
} catch(std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
// Rethrow the exception
|
||||
|
|
@ -285,13 +298,13 @@ public:
|
|||
|
||||
std::fstream out(loc, std::fstream::out | std::fstream::binary);
|
||||
if(out.good()) {
|
||||
m_layers_rst[i].first.save(out, Raster::Compression::PNG);
|
||||
m_layers_rst[i].raster.save(out, Raster::Compression::PNG);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Can't create file for layer";
|
||||
}
|
||||
|
||||
out.close();
|
||||
m_layers_rst[i].first.reset();
|
||||
m_layers_rst[i].raster.reset();
|
||||
}
|
||||
|
||||
void set_statistics(const std::vector<double> statistics)
|
||||
|
|
|
|||
|
|
@ -1790,15 +1790,21 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
|||
if (! volumes.empty()) {
|
||||
// Compose mesh.
|
||||
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||
TriangleMesh mesh;
|
||||
for (const ModelVolume *v : volumes)
|
||||
{
|
||||
TriangleMesh vol_mesh(v->mesh);
|
||||
vol_mesh.transform(v->get_matrix());
|
||||
TriangleMesh mesh(volumes.front()->mesh);
|
||||
mesh.transform(volumes.front()->get_matrix(), true);
|
||||
assert(mesh.repaired);
|
||||
if (volumes.size() == 1 && mesh.repaired) {
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
stl_check_facets_exact(&mesh.stl);
|
||||
}
|
||||
for (size_t idx_volume = 1; idx_volume < volumes.size(); ++ idx_volume) {
|
||||
const ModelVolume &model_volume = *volumes[idx_volume];
|
||||
TriangleMesh vol_mesh(model_volume.mesh);
|
||||
vol_mesh.transform(model_volume.get_matrix(), true);
|
||||
mesh.merge(vol_mesh);
|
||||
}
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo);
|
||||
mesh.transform(m_trafo, true);
|
||||
// apply XY shift
|
||||
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
|
||||
// perform actual slicing
|
||||
|
|
@ -1819,9 +1825,13 @@ std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z,
|
|||
// Compose mesh.
|
||||
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||
TriangleMesh mesh(volume.mesh);
|
||||
mesh.transform(volume.get_matrix());
|
||||
mesh.transform(volume.get_matrix(), true);
|
||||
if (mesh.repaired) {
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
stl_check_facets_exact(&mesh.stl);
|
||||
}
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo);
|
||||
mesh.transform(m_trafo, true);
|
||||
// apply XY shift
|
||||
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
|
||||
// perform actual slicing
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include "Rasterizer.hpp"
|
||||
#include <ExPolygon.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
// For rasterizing
|
||||
#include <agg/agg_basics.h>
|
||||
|
|
@ -15,8 +14,8 @@
|
|||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
|
||||
// For png compression
|
||||
#include <png/writer.hpp>
|
||||
// Experimental minz image write:
|
||||
#include <miniz/miniz_tdef.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
@ -91,6 +90,25 @@ public:
|
|||
agg::render_scanlines(ras, scanlines, m_renderer);
|
||||
}
|
||||
|
||||
void draw(const ClipperLib::Polygon &poly) {
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_p8 scanlines;
|
||||
|
||||
auto&& path = to_path(poly.Contour);
|
||||
|
||||
if(m_o == Origin::TOP_LEFT) flipy(path);
|
||||
|
||||
ras.add_path(path);
|
||||
|
||||
for(auto h : poly.Holes) {
|
||||
auto&& holepath = to_path(h);
|
||||
if(m_o == Origin::TOP_LEFT) flipy(holepath);
|
||||
ras.add_path(holepath);
|
||||
}
|
||||
|
||||
agg::render_scanlines(ras, scanlines, m_renderer);
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
m_raw_renderer.clear(ColorBlack);
|
||||
}
|
||||
|
|
@ -110,14 +128,36 @@ private:
|
|||
return p(1) * SCALING_FACTOR/m_pxdim.h_mm;
|
||||
}
|
||||
|
||||
agg::path_storage to_path(const Polygon& poly) {
|
||||
agg::path_storage to_path(const Polygon& poly)
|
||||
{
|
||||
agg::path_storage path;
|
||||
|
||||
auto it = poly.points.begin();
|
||||
path.move_to(getPx(*it), getPy(*it));
|
||||
while(++it != poly.points.end())
|
||||
while(++it != poly.points.end()) path.line_to(getPx(*it), getPy(*it));
|
||||
path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
double getPx(const ClipperLib::IntPoint& p) {
|
||||
return p.X * SCALING_FACTOR/m_pxdim.w_mm;
|
||||
}
|
||||
|
||||
double getPy(const ClipperLib::IntPoint& p) {
|
||||
return p.Y * SCALING_FACTOR/m_pxdim.h_mm;
|
||||
}
|
||||
|
||||
agg::path_storage to_path(const ClipperLib::Path& poly)
|
||||
{
|
||||
agg::path_storage path;
|
||||
auto it = poly.begin();
|
||||
path.move_to(getPx(*it), getPy(*it));
|
||||
while(++it != poly.end())
|
||||
path.line_to(getPx(*it), getPy(*it));
|
||||
|
||||
path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
|
||||
path.line_to(getPx(poly.front()), getPy(poly.front()));
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
@ -169,38 +209,36 @@ void Raster::clear()
|
|||
m_impl->clear();
|
||||
}
|
||||
|
||||
void Raster::draw(const ExPolygon &poly)
|
||||
void Raster::draw(const ExPolygon &expoly)
|
||||
{
|
||||
m_impl->draw(expoly);
|
||||
}
|
||||
|
||||
void Raster::draw(const ClipperLib::Polygon &poly)
|
||||
{
|
||||
assert(m_impl);
|
||||
m_impl->draw(poly);
|
||||
}
|
||||
|
||||
void Raster::save(std::ostream& stream, Compression comp)
|
||||
{
|
||||
assert(m_impl);
|
||||
if(!stream.good()) return;
|
||||
|
||||
switch(comp) {
|
||||
case Compression::PNG: {
|
||||
|
||||
png::writer<std::ostream> wr(stream);
|
||||
|
||||
wr.set_bit_depth(8);
|
||||
wr.set_color_type(png::color_type_gray);
|
||||
wr.set_width(resolution().width_px);
|
||||
wr.set_height(resolution().height_px);
|
||||
wr.set_compression_type(png::compression_type_default);
|
||||
|
||||
wr.write_info();
|
||||
|
||||
auto& b = m_impl->buffer();
|
||||
auto ptr = reinterpret_cast<png::byte*>( b.data() );
|
||||
unsigned stride =
|
||||
sizeof(Impl::TBuffer::value_type) * resolution().width_px;
|
||||
size_t out_len = 0;
|
||||
void * rawdata = tdefl_write_image_to_png_file_in_memory(
|
||||
b.data(),
|
||||
int(resolution().width_px),
|
||||
int(resolution().height_px), 1, &out_len);
|
||||
|
||||
for(unsigned r = 0; r < resolution().height_px; r++, ptr+=stride) {
|
||||
wr.write_row(ptr);
|
||||
}
|
||||
if(rawdata == nullptr) break;
|
||||
|
||||
wr.write_end_info();
|
||||
stream.write(static_cast<const char*>(rawdata),
|
||||
std::streamsize(out_len));
|
||||
|
||||
MZ_FREE(rawdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -217,4 +255,47 @@ void Raster::save(std::ostream& stream, Compression comp)
|
|||
}
|
||||
}
|
||||
|
||||
RawBytes Raster::save(Raster::Compression comp)
|
||||
{
|
||||
assert(m_impl);
|
||||
|
||||
std::uint8_t *ptr = nullptr; size_t s = 0;
|
||||
|
||||
switch(comp) {
|
||||
case Compression::PNG: {
|
||||
|
||||
void *rawdata = tdefl_write_image_to_png_file_in_memory(
|
||||
m_impl->buffer().data(),
|
||||
int(resolution().width_px),
|
||||
int(resolution().height_px), 1, &s);
|
||||
|
||||
if(rawdata == nullptr) break;
|
||||
|
||||
ptr = static_cast<std::uint8_t*>(rawdata);
|
||||
|
||||
break;
|
||||
}
|
||||
case Compression::RAW: {
|
||||
auto header = std::string("P5 ") +
|
||||
std::to_string(m_impl->resolution().width_px) + " " +
|
||||
std::to_string(m_impl->resolution().height_px) + " " + "255 ";
|
||||
|
||||
auto sz = m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type);
|
||||
|
||||
s = sz + header.size();
|
||||
ptr = static_cast<std::uint8_t*>(MZ_MALLOC(s));
|
||||
|
||||
auto buff = reinterpret_cast<std::uint8_t*>(m_impl->buffer().data());
|
||||
std::copy(buff, buff+sz, ptr + header.size());
|
||||
}
|
||||
}
|
||||
|
||||
return {ptr, s};
|
||||
}
|
||||
|
||||
void RawBytes::MinzDeleter::operator()(uint8_t *rawptr)
|
||||
{
|
||||
MZ_FREE(rawptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,52 @@
|
|||
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ClipperLib { struct Polygon; }
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ExPolygon;
|
||||
|
||||
// Raw byte buffer paired with its size. Suitable for compressed PNG data.
|
||||
class RawBytes {
|
||||
|
||||
class MinzDeleter {
|
||||
public:
|
||||
void operator()(std::uint8_t *rawptr);
|
||||
};
|
||||
|
||||
std::unique_ptr<std::uint8_t, MinzDeleter> m_buffer = nullptr;
|
||||
size_t m_size = 0;
|
||||
|
||||
public:
|
||||
|
||||
RawBytes() = default;
|
||||
RawBytes(std::uint8_t *rawptr, size_t s): m_buffer(rawptr), m_size(s) {}
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
const uint8_t * data() { return m_buffer.get(); }
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// FIXME: the following is needed for MSVC2013 compatibility
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RawBytes(const RawBytes&) = delete;
|
||||
RawBytes(RawBytes&& mv):
|
||||
m_buffer(std::move(mv.m_buffer)), m_size(mv.m_size) {}
|
||||
|
||||
RawBytes& operator=(const RawBytes&) = delete;
|
||||
RawBytes& operator=(RawBytes&& mv) {
|
||||
m_buffer.swap(mv.m_buffer);
|
||||
m_size = mv.m_size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Raster captures an anti-aliased monochrome canvas where vectorial
|
||||
* polygons can be rasterized. Fill color is always white and the background is
|
||||
|
|
@ -84,9 +125,12 @@ public:
|
|||
|
||||
/// Draw a polygon with holes.
|
||||
void draw(const ExPolygon& poly);
|
||||
void draw(const ClipperLib::Polygon& poly);
|
||||
|
||||
/// Save the raster on the specified stream.
|
||||
void save(std::ostream& stream, Compression comp = Compression::RAW);
|
||||
|
||||
RawBytes save(Compression comp = Compression::RAW);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ float SLAAutoSupports::distance_limit(float angle) const
|
|||
}*/
|
||||
|
||||
SLAAutoSupports::SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices, const std::vector<float>& heights,
|
||||
const Config& config, std::function<void(void)> throw_on_cancel)
|
||||
: m_config(config), m_emesh(emesh), m_throw_on_cancel(throw_on_cancel)
|
||||
const Config& config, std::function<void(void)> throw_on_cancel, std::function<void(int)> statusfn)
|
||||
: m_config(config), m_emesh(emesh), m_throw_on_cancel(throw_on_cancel), m_statusfn(statusfn)
|
||||
{
|
||||
process(slices, heights);
|
||||
project_onto_mesh(m_output);
|
||||
|
|
@ -197,6 +197,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
|||
PointGrid3D point_grid;
|
||||
point_grid.cell_size = Vec3f(10.f, 10.f, 10.f);
|
||||
|
||||
double increment = 100.0 / layers.size();
|
||||
double status = 0;
|
||||
|
||||
for (unsigned int layer_id = 0; layer_id < layers.size(); ++ layer_id) {
|
||||
SLAAutoSupports::MyLayer *layer_top = &layers[layer_id];
|
||||
SLAAutoSupports::MyLayer *layer_bottom = (layer_id > 0) ? &layers[layer_id - 1] : nullptr;
|
||||
|
|
@ -252,6 +255,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
|||
|
||||
m_throw_on_cancel();
|
||||
|
||||
status += increment;
|
||||
m_statusfn(int(std::round(status)));
|
||||
|
||||
#ifdef SLA_AUTOSUPPORTS_DEBUG
|
||||
/*std::string layer_num_str = std::string((i<10 ? "0" : "")) + std::string((i<100 ? "0" : "")) + std::to_string(i);
|
||||
output_expolygons(expolys_top, "top" + layer_num_str + ".svg");
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public:
|
|||
};
|
||||
|
||||
SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
|
||||
const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel);
|
||||
const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel, std::function<void(int)> statusfn);
|
||||
const std::vector<sla::SupportPoint>& output() { return m_output; }
|
||||
|
||||
struct MyLayer;
|
||||
|
|
@ -196,12 +196,13 @@ private:
|
|||
static void output_structures(const std::vector<Structure> &structures);
|
||||
#endif // SLA_AUTOSUPPORTS_DEBUG
|
||||
|
||||
std::function<void(void)> m_throw_on_cancel;
|
||||
const sla::EigenMesh3D& m_emesh;
|
||||
std::function<void(void)> m_throw_on_cancel;
|
||||
std::function<void(int)> m_statusfn;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
#endif // SLAAUTOSUPPORTS_HPP_
|
||||
#endif // SLAAUTOSUPPORTS_HPP_
|
||||
|
|
|
|||
|
|
@ -755,9 +755,12 @@ public:
|
|||
return m_compact_bridges;
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_integral<T>::value, const Pillar&>::type
|
||||
pillar(T id) const { assert(id >= 0); return m_pillars.at(size_t(id)); }
|
||||
template<class T> inline const Pillar& pillar(T id) const {
|
||||
static_assert(std::is_integral<T>::value, "Invalid index type");
|
||||
assert(id >= 0 && id < m_pillars.size() &&
|
||||
id < std::numeric_limits<size_t>::max());
|
||||
return m_pillars[size_t(id)];
|
||||
}
|
||||
|
||||
const Pad& create_pad(const TriangleMesh& object_supports,
|
||||
const ExPolygons& baseplate,
|
||||
|
|
@ -1463,7 +1466,7 @@ public:
|
|||
m_cfg.head_back_radius_mm,
|
||||
w);
|
||||
|
||||
if(t <= w || (hp(Z) + nn(Z) * w) < m_result.ground_level) {
|
||||
if(t <= w) {
|
||||
|
||||
// Let's try to optimize this angle, there might be a
|
||||
// viable normal that doesn't collide with the model
|
||||
|
|
@ -1506,7 +1509,7 @@ public:
|
|||
// save the verified and corrected normal
|
||||
m_support_nmls.row(fidx) = nn;
|
||||
|
||||
if(t > w && (hp(Z) + nn(Z) * w) > m_result.ground_level) {
|
||||
if(t > w) {
|
||||
// mark the point for needing a head.
|
||||
m_iheads.emplace_back(fidx);
|
||||
} else if( polar >= 3*PI/4 ) {
|
||||
|
|
@ -2237,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
SlicedSupports SLASupportTree::slice(const std::vector<float> &heights,
|
||||
float cr) const
|
||||
{
|
||||
TriangleMesh fullmesh = m_impl->merged_mesh();
|
||||
fullmesh.merge(get_pad());
|
||||
TriangleMeshSlicer slicer(&fullmesh);
|
||||
SlicedSupports ret;
|
||||
slicer.slice(heights, cr, &ret, get().ctl().cancelfn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
|
||||
const PoolConfig& pcfg) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ public:
|
|||
/// Get the sliced 2d layers of the support geometry.
|
||||
SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
|
||||
|
||||
SlicedSupports slice(const std::vector<float>&, float closing_radius) const;
|
||||
|
||||
/// Adding the "pad" (base pool) under the supports
|
||||
const TriangleMesh& add_pad(const SliceLayer& baseplate,
|
||||
const PoolConfig& pcfg) const;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -6,12 +6,14 @@
|
|||
#include "PrintExport.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
#include "Zipper.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum SLAPrintStep : unsigned int {
|
||||
slapsRasterize,
|
||||
slapsValidate,
|
||||
slapsMergeSlicesAndEval,
|
||||
slapsRasterize,
|
||||
slapsCount
|
||||
};
|
||||
|
||||
|
|
@ -20,8 +22,7 @@ enum SLAPrintObjectStep : unsigned int {
|
|||
slaposSupportPoints,
|
||||
slaposSupportTree,
|
||||
slaposBasePool,
|
||||
slaposSliceSupports,
|
||||
slaposIndexSlices,
|
||||
slaposSliceSupports,
|
||||
slaposCount
|
||||
};
|
||||
|
||||
|
|
@ -33,7 +34,9 @@ using _SLAPrintObjectBase =
|
|||
|
||||
// Layers according to quantized height levels. This will be consumed by
|
||||
// the printer (rasterizer) in the SLAPrint class.
|
||||
using LevelID = long long;
|
||||
// using coord_t = long long;
|
||||
|
||||
enum SliceOrigin { soSupport, soModel };
|
||||
|
||||
class SLAPrintObject : public _SLAPrintObjectBase
|
||||
{
|
||||
|
|
@ -41,8 +44,14 @@ private: // Prevents erroneous use by other classes.
|
|||
using Inherited = _SLAPrintObjectBase;
|
||||
|
||||
public:
|
||||
|
||||
// I refuse to grantee copying (Tamas)
|
||||
SLAPrintObject(const SLAPrintObject&) = delete;
|
||||
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
|
||||
|
||||
const SLAPrintObjectConfig& config() const { return m_config; }
|
||||
const Transform3d& trafo() const { return m_trafo; }
|
||||
bool is_left_handed() const { return m_left_handed; }
|
||||
|
||||
struct Instance {
|
||||
Instance(ModelID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {}
|
||||
|
|
@ -82,39 +91,145 @@ public:
|
|||
// pad is not, then without the pad, otherwise the full value is returned.
|
||||
double get_current_elevation() const;
|
||||
|
||||
// These two methods should be callable on the client side (e.g. UI thread)
|
||||
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
|
||||
// are ready. All the print objects are processed before slapsRasterize so
|
||||
// it is safe to call them during and/or after slapsRasterize.
|
||||
const std::vector<ExPolygons>& get_model_slices() const;
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
|
||||
// This method returns the support points of this SLAPrintObject.
|
||||
const std::vector<sla::SupportPoint>& get_support_points() const;
|
||||
|
||||
// An index record referencing the slices
|
||||
// (get_model_slices(), get_support_slices()) where the keys are the height
|
||||
// levels of the model in scaled-clipper coordinates. The levels correspond
|
||||
// to the z coordinate of the object coordinate system.
|
||||
struct SliceRecord {
|
||||
using Key = float;
|
||||
// The public Slice record structure. It corresponds to one printable layer.
|
||||
class SliceRecord {
|
||||
public:
|
||||
// this will be the max limit of size_t
|
||||
static const size_t NONE = size_t(-1);
|
||||
|
||||
using Idx = size_t;
|
||||
static const Idx NONE = Idx(-1); // this will be the max limit of size_t
|
||||
static const SliceRecord EMPTY;
|
||||
|
||||
Idx model_slices_idx = NONE;
|
||||
Idx support_slices_idx = NONE;
|
||||
private:
|
||||
coord_t m_print_z = 0; // Top of the layer
|
||||
float m_slice_z = 0.f; // Exact level of the slice
|
||||
float m_height = 0.f; // Height of the sliced layer
|
||||
|
||||
size_t m_model_slices_idx = NONE;
|
||||
size_t m_support_slices_idx = NONE;
|
||||
const SLAPrintObject *m_po = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
SliceRecord(coord_t key, float slicez, float height):
|
||||
m_print_z(key), m_slice_z(slicez), m_height(height) {}
|
||||
|
||||
// The key will be the integer height level of the top of the layer.
|
||||
coord_t print_level() const { return m_print_z; }
|
||||
|
||||
// Returns the exact floating point Z coordinate of the slice
|
||||
float slice_level() const { return m_slice_z; }
|
||||
|
||||
// Returns the current layer height
|
||||
float layer_height() const { return m_height; }
|
||||
|
||||
bool is_valid() const { return ! std::isnan(m_slice_z); }
|
||||
|
||||
const SLAPrintObject* print_obj() const { assert(m_po); return m_po; }
|
||||
|
||||
// Methods for setting the indices into the slice vectors.
|
||||
void set_model_slice_idx(const SLAPrintObject &po, size_t id) {
|
||||
m_po = &po; m_model_slices_idx = id;
|
||||
}
|
||||
|
||||
void set_support_slice_idx(const SLAPrintObject& po, size_t id) {
|
||||
m_po = &po; m_support_slices_idx = id;
|
||||
}
|
||||
|
||||
const ExPolygons& get_slice(SliceOrigin o) const;
|
||||
};
|
||||
|
||||
using SliceIndex = std::map<SliceRecord::Key, SliceRecord>;
|
||||
private:
|
||||
|
||||
// Retrieve the slice index which is readable only after slaposIndexSlices
|
||||
// is done.
|
||||
const SliceIndex& get_slice_index() const;
|
||||
template <class T> inline static T level(const SliceRecord& sr) {
|
||||
static_assert(std::is_arithmetic<T>::value, "Arithmetic only!");
|
||||
return std::is_integral<T>::value ? T(sr.print_level()) : T(sr.slice_level());
|
||||
}
|
||||
|
||||
// I refuse to grantee copying (Tamas)
|
||||
SLAPrintObject(const SLAPrintObject&) = delete;
|
||||
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
|
||||
template <class T> inline static SliceRecord create_slice_record(T val) {
|
||||
static_assert(std::is_arithmetic<T>::value, "Arithmetic only!");
|
||||
return std::is_integral<T>::value ? SliceRecord{ coord_t(val), 0.f, 0.f } : SliceRecord{ 0, float(val), 0.f };
|
||||
}
|
||||
|
||||
// This is a template method for searching the slice index either by
|
||||
// an integer key: print_level or a floating point key: slice_level.
|
||||
// The eps parameter gives the max deviation in + or - direction.
|
||||
//
|
||||
// This method can be used in const or non-const contexts as well.
|
||||
template<class Container, class T>
|
||||
static auto closest_slice_record(
|
||||
Container& cont,
|
||||
T lvl,
|
||||
T eps = std::numeric_limits<T>::max()) -> decltype (cont.begin())
|
||||
{
|
||||
if(cont.empty()) return cont.end();
|
||||
if(cont.size() == 1 && std::abs(level<T>(cont.front()) - lvl) > eps)
|
||||
return cont.end();
|
||||
|
||||
SliceRecord query = create_slice_record(lvl);
|
||||
|
||||
auto it = std::lower_bound(cont.begin(), cont.end(), query,
|
||||
[](const SliceRecord& r1,
|
||||
const SliceRecord& r2)
|
||||
{
|
||||
return level<T>(r1) < level<T>(r2);
|
||||
});
|
||||
|
||||
T diff = std::abs(level<T>(*it) - lvl);
|
||||
|
||||
if(it != cont.begin()) {
|
||||
auto it_prev = std::prev(it);
|
||||
T diff_prev = std::abs(level<T>(*it_prev) - lvl);
|
||||
if(diff_prev < diff) { diff = diff_prev; it = it_prev; }
|
||||
}
|
||||
|
||||
if(diff > eps) it = cont.end();
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
const std::vector<ExPolygons>& get_model_slices() const { return m_model_slices; }
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
|
||||
public:
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These methods should be callable on the client side (e.g. UI thread)
|
||||
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
|
||||
// are ready. All the print objects are processed before slapsRasterize so
|
||||
// it is safe to call them during and/or after slapsRasterize.
|
||||
//
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Retrieve the slice index.
|
||||
const std::vector<SliceRecord>& get_slice_index() const {
|
||||
return m_slice_index;
|
||||
}
|
||||
|
||||
// Search slice index for the closest slice to given print_level.
|
||||
// max_epsilon gives the allowable deviation of the returned slice record's
|
||||
// level.
|
||||
const SliceRecord& closest_slice_to_print_level(
|
||||
coord_t print_level,
|
||||
coord_t max_epsilon = std::numeric_limits<coord_t>::max()) const
|
||||
{
|
||||
auto it = closest_slice_record(m_slice_index, print_level, max_epsilon);
|
||||
return it == m_slice_index.end() ? SliceRecord::EMPTY : *it;
|
||||
}
|
||||
|
||||
// Search slice index for the closest slice to given slice_level.
|
||||
// max_epsilon gives the allowable deviation of the returned slice record's
|
||||
// level. Use SliceRecord::is_valid() to check the result.
|
||||
const SliceRecord& closest_slice_to_slice_level(
|
||||
float slice_level,
|
||||
float max_epsilon = std::numeric_limits<float>::max()) const
|
||||
{
|
||||
auto it = closest_slice_record(m_slice_index, slice_level, max_epsilon);
|
||||
return it == m_slice_index.end() ? SliceRecord::EMPTY : *it;
|
||||
}
|
||||
|
||||
protected:
|
||||
// to be called from SLAPrint only.
|
||||
|
|
@ -127,11 +242,12 @@ protected:
|
|||
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false)
|
||||
{ this->m_config.apply_only(other, keys, ignore_nonexistent); }
|
||||
|
||||
void set_trafo(const Transform3d& trafo) {
|
||||
m_transformed_rmesh.invalidate([this, &trafo](){ m_trafo = trafo; });
|
||||
void set_trafo(const Transform3d& trafo, bool left_handed) {
|
||||
m_transformed_rmesh.invalidate([this, &trafo, left_handed](){ m_trafo = trafo; m_left_handed = left_handed; });
|
||||
}
|
||||
|
||||
void set_instances(const std::vector<Instance> &instances) { m_instances = instances; }
|
||||
template<class InstVec> inline void set_instances(InstVec&& instances) { m_instances = std::forward<InstVec>(instances); }
|
||||
|
||||
// Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint.
|
||||
bool invalidate_step(SLAPrintObjectStep step);
|
||||
bool invalidate_all_steps();
|
||||
|
|
@ -145,8 +261,12 @@ protected:
|
|||
private:
|
||||
// Object specific configuration, pulled from the configuration layer.
|
||||
SLAPrintObjectConfig m_config;
|
||||
|
||||
// Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
|
||||
Transform3d m_trafo = Transform3d::Identity();
|
||||
// m_trafo is left handed -> 3x3 affine transformation has negative determinant.
|
||||
bool m_left_handed = false;
|
||||
|
||||
std::vector<Instance> m_instances;
|
||||
|
||||
// Individual 2d slice polygons from lower z to higher z levels
|
||||
|
|
@ -154,11 +274,9 @@ private:
|
|||
|
||||
// Exact (float) height levels mapped to the slices. Each record contains
|
||||
// the index to the model and the support slice vectors.
|
||||
SliceIndex m_slice_index;
|
||||
std::vector<SliceRecord> m_slice_index;
|
||||
|
||||
// The height levels corrected and scaled up in integer values. This will
|
||||
// be used at rasterization.
|
||||
std::vector<LevelID> m_level_ids;
|
||||
std::vector<float> m_model_height_levels;
|
||||
|
||||
// Caching the transformed (m_trafo) raw mesh of the object
|
||||
mutable CachedObject<TriangleMesh> m_transformed_rmesh;
|
||||
|
|
@ -169,6 +287,8 @@ private:
|
|||
|
||||
using PrintObjects = std::vector<SLAPrintObject*>;
|
||||
|
||||
using SliceRecord = SLAPrintObject::SliceRecord;
|
||||
|
||||
class TriangleMesh;
|
||||
|
||||
struct SLAPrintStatistics
|
||||
|
|
@ -200,6 +320,37 @@ struct SLAPrintStatistics
|
|||
}
|
||||
};
|
||||
|
||||
// The implementation of creating zipped archives with wxWidgets
|
||||
template<> class LayerWriter<Zipper> {
|
||||
Zipper m_zip;
|
||||
public:
|
||||
|
||||
LayerWriter(const std::string& zipfile_path): m_zip(zipfile_path) {}
|
||||
|
||||
void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
|
||||
|
||||
void binary_entry(const std::string& fname,
|
||||
const std::uint8_t* buf,
|
||||
size_t l)
|
||||
{
|
||||
m_zip.add_entry(fname, buf, l);
|
||||
}
|
||||
|
||||
template<class T> inline LayerWriter& operator<<(T&& arg) {
|
||||
m_zip << std::forward<T>(arg); return *this;
|
||||
}
|
||||
|
||||
bool is_ok() const {
|
||||
return true; // m_zip blows up if something goes wrong...
|
||||
}
|
||||
|
||||
// After finalize, no writing to the archive will have an effect. The only
|
||||
// valid operation is to dispose the object calling the destructor which
|
||||
// should close the file. This method can throw and signal potential errors
|
||||
// when flushing the archive. This is why its present.
|
||||
void finalize() { m_zip.finalize(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class is the high level FSM for the SLA printing process.
|
||||
*
|
||||
|
|
@ -214,6 +365,7 @@ private: // Prevents erroneous use by other classes.
|
|||
typedef PrintBaseWithState<SLAPrintStep, slapsCount> Inherited;
|
||||
|
||||
public:
|
||||
|
||||
SLAPrint(): m_stepmask(slapsCount, true) {}
|
||||
|
||||
virtual ~SLAPrint() override { this->clear(); }
|
||||
|
|
@ -229,31 +381,79 @@ public:
|
|||
// Returns true if an object step is done on all objects and there's at least one object.
|
||||
bool is_step_done(SLAPrintObjectStep step) const;
|
||||
// Returns true if the last step was finished with success.
|
||||
bool finished() const override { return this->is_step_done(slaposIndexSlices) && this->Inherited::is_step_done(slapsRasterize); }
|
||||
bool finished() const override { return this->is_step_done(slaposSliceSupports) && this->Inherited::is_step_done(slapsRasterize); }
|
||||
|
||||
template<class Fmt> void export_raster(const std::string& fname) {
|
||||
if(m_printer) m_printer->save<Fmt>(fname);
|
||||
template<class Fmt = Zipper>
|
||||
inline void export_raster(const std::string& fpath,
|
||||
const std::string& projectname = "")
|
||||
{
|
||||
if(m_printer) m_printer->save<Fmt>(fpath, projectname);
|
||||
}
|
||||
|
||||
const PrintObjects& objects() const { return m_objects; }
|
||||
|
||||
const SLAPrintConfig& print_config() const { return m_print_config; }
|
||||
const SLAPrinterConfig& printer_config() const { return m_printer_config; }
|
||||
const SLAMaterialConfig& material_config() const { return m_material_config; }
|
||||
const SLAPrintObjectConfig& default_object_config() const { return m_default_object_config; }
|
||||
|
||||
std::string output_filename() const override;
|
||||
|
||||
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
|
||||
|
||||
std::string validate() const override;
|
||||
|
||||
// An aggregation of SliceRecord-s from all the print objects for each
|
||||
// occupied layer. Slice record levels dont have to match exactly.
|
||||
// They are unified if the level difference is within +/- SCALED_EPSILON
|
||||
class PrintLayer {
|
||||
coord_t m_level;
|
||||
|
||||
// The collection of slice records for the current level.
|
||||
std::vector<std::reference_wrapper<const SliceRecord>> m_slices;
|
||||
|
||||
std::vector<ClipperLib::Polygon> m_transformed_slices;
|
||||
|
||||
template<class Container> void transformed_slices(Container&& c) {
|
||||
m_transformed_slices = std::forward<Container>(c);
|
||||
}
|
||||
|
||||
friend void SLAPrint::process();
|
||||
|
||||
public:
|
||||
|
||||
explicit PrintLayer(coord_t lvl) : m_level(lvl) {}
|
||||
|
||||
// for being sorted in their container (see m_printer_input)
|
||||
bool operator<(const PrintLayer& other) const {
|
||||
return m_level < other.m_level;
|
||||
}
|
||||
|
||||
void add(const SliceRecord& sr) { m_slices.emplace_back(sr); }
|
||||
|
||||
coord_t level() const { return m_level; }
|
||||
|
||||
auto slices() const -> const decltype (m_slices)& { return m_slices; }
|
||||
|
||||
const std::vector<ClipperLib::Polygon> & transformed_slices() const {
|
||||
return m_transformed_slices;
|
||||
}
|
||||
};
|
||||
|
||||
// The aggregated and leveled print records from various objects.
|
||||
// TODO: use this structure for the preview in the future.
|
||||
const std::vector<PrintLayer>& print_layers() const { return m_printer_input; }
|
||||
|
||||
private:
|
||||
using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>;
|
||||
using SLAPrinterPtr = std::unique_ptr<SLAPrinter>;
|
||||
|
||||
// Implement same logic as in SLAPrintObject
|
||||
bool invalidate_step(SLAPrintStep st);
|
||||
|
||||
// Invalidate steps based on a set of parameters changed.
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
|
||||
std::vector<float> calculate_heights(const BoundingBoxf3& bb,
|
||||
float elevation,
|
||||
float initial_layer_height,
|
||||
float layer_height) const;
|
||||
|
||||
void fill_statistics();
|
||||
|
||||
SLAPrintConfig m_print_config;
|
||||
SLAPrinterConfig m_printer_config;
|
||||
SLAMaterialConfig m_material_config;
|
||||
|
|
@ -262,23 +462,8 @@ private:
|
|||
PrintObjects m_objects;
|
||||
std::vector<bool> m_stepmask;
|
||||
|
||||
// Definition of the print input map. It consists of the slices indexed
|
||||
// with scaled (clipper) Z coordinates. Also contains the instance
|
||||
// transformations in scaled and filtered version. This is enough for the
|
||||
// rasterizer to be able to draw every layer in the right position
|
||||
using Layer = ExPolygons;
|
||||
using LayerCopies = std::vector<SLAPrintObject::Instance>;
|
||||
struct LayerRef {
|
||||
std::reference_wrapper<const Layer> lref;
|
||||
std::reference_wrapper<const LayerCopies> copies;
|
||||
LayerRef(const Layer& lyr, const LayerCopies& cp) :
|
||||
lref(std::cref(lyr)), copies(std::cref(cp)) {}
|
||||
};
|
||||
|
||||
// One level may contain multiple slices from multiple objects and their
|
||||
// supports
|
||||
using LayerRefs = std::vector<LayerRef>;
|
||||
std::map<LevelID, LayerRefs> m_printer_input;
|
||||
// Ready-made data for rasterization.
|
||||
std::vector<PrintLayer> m_printer_input;
|
||||
|
||||
// The printer itself
|
||||
SLAPrinterPtr m_printer;
|
||||
|
|
@ -286,6 +471,15 @@ private:
|
|||
// Estimated print time, material consumed.
|
||||
SLAPrintStatistics m_print_statistics;
|
||||
|
||||
class StatusReporter {
|
||||
double m_st = 0;
|
||||
public:
|
||||
void operator() (SLAPrint& p, double st, const std::string& msg,
|
||||
unsigned flags = SlicingStatus::DEFAULT);
|
||||
double status() const { return m_st; }
|
||||
} m_report_status;
|
||||
|
||||
|
||||
friend SLAPrintObject;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,8 @@
|
|||
|
||||
// Disable synchronization of unselected instances
|
||||
#define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1)
|
||||
// Scene's GUI made using imgui library
|
||||
#define ENABLE_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
|
||||
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI)
|
||||
// Disable imgui dialog for move, rotate and scale gizmos
|
||||
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
|
||||
// Use wxDataViewRender instead of wxDataViewCustomRenderer
|
||||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
||||
|
||||
|
|
@ -34,8 +33,6 @@
|
|||
|
||||
// Changed algorithm to extract euler angles from rotation matrix
|
||||
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Added minimum threshold for click and drag movements
|
||||
#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Modified initial default placement of generic subparts
|
||||
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Bunch of fixes related to volumes centering
|
||||
|
|
@ -59,4 +56,5 @@
|
|||
// Toolbars and Gizmos use icons imported from svg files
|
||||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
||||
|
||||
|
||||
#endif // _technologies_h_
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& f
|
|||
stl.stats.original_num_facets = stl.stats.number_of_facets;
|
||||
stl_allocate(&stl);
|
||||
|
||||
for (int i = 0; i < stl.stats.number_of_facets; i++) {
|
||||
for (uint32_t i = 0; i < stl.stats.number_of_facets; i++) {
|
||||
stl_facet facet;
|
||||
facet.vertex[0] = points[facets[i](0)].cast<float>();
|
||||
facet.vertex[1] = points[facets[i](1)].cast<float>();
|
||||
|
|
@ -125,9 +125,9 @@ void TriangleMesh::repair()
|
|||
float tolerance = stl.stats.shortest_edge;
|
||||
float increment = stl.stats.bounding_diameter / 10000.0;
|
||||
int iterations = 2;
|
||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
|
||||
#ifdef SLIC3R_TRACE_REPAIR
|
||||
BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_nearby";
|
||||
|
|
@ -143,7 +143,7 @@ void TriangleMesh::repair()
|
|||
}
|
||||
|
||||
// remove_unconnected
|
||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||
#ifdef SLIC3R_TRACE_REPAIR
|
||||
BOOST_LOG_TRIVIAL(trace) << "\tstl_remove_unconnected_facets";
|
||||
#endif /* SLIC3R_TRACE_REPAIR */
|
||||
|
|
@ -212,9 +212,9 @@ void TriangleMesh::check_topology()
|
|||
float tolerance = stl.stats.shortest_edge;
|
||||
float increment = stl.stats.bounding_diameter / 10000.0;
|
||||
int iterations = 2;
|
||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
|
||||
stl_check_facets_nearby(&stl, tolerance);
|
||||
//printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
|
||||
|
|
@ -273,6 +273,11 @@ void TriangleMesh::translate(float x, float y, float z)
|
|||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::translate(const Vec3f &displacement)
|
||||
{
|
||||
translate(displacement(0), displacement(1), displacement(2));
|
||||
}
|
||||
|
||||
void TriangleMesh::rotate(float angle, const Axis &axis)
|
||||
{
|
||||
if (angle == 0.f)
|
||||
|
|
@ -314,10 +319,15 @@ void TriangleMesh::mirror(const Axis &axis)
|
|||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::transform(const Transform3d& t)
|
||||
void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
|
||||
{
|
||||
stl_transform(&stl, t);
|
||||
stl_invalidate_shared_vertices(&stl);
|
||||
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
|
||||
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
||||
this->repair();
|
||||
stl_reverse_all_facets(&stl);
|
||||
}
|
||||
}
|
||||
|
||||
void TriangleMesh::align_to_origin()
|
||||
|
|
@ -338,113 +348,79 @@ void TriangleMesh::rotate(double angle, Point* center)
|
|||
this->translate(c(0), c(1), 0);
|
||||
}
|
||||
|
||||
bool TriangleMesh::has_multiple_patches() const
|
||||
/**
|
||||
* Calculates whether or not the mesh is splittable.
|
||||
*/
|
||||
bool TriangleMesh::is_splittable() const
|
||||
{
|
||||
// we need neighbors
|
||||
if (!this->repaired)
|
||||
throw std::runtime_error("split() requires repair()");
|
||||
|
||||
if (this->stl.stats.number_of_facets == 0)
|
||||
return false;
|
||||
std::vector<unsigned char> visited;
|
||||
find_unvisited_neighbors(visited);
|
||||
|
||||
std::vector<int> facet_queue(this->stl.stats.number_of_facets, 0);
|
||||
std::vector<char> facet_visited(this->stl.stats.number_of_facets, false);
|
||||
int facet_queue_cnt = 1;
|
||||
facet_queue[0] = 0;
|
||||
facet_visited[0] = true;
|
||||
while (facet_queue_cnt > 0) {
|
||||
int facet_idx = facet_queue[-- facet_queue_cnt];
|
||||
facet_visited[facet_idx] = true;
|
||||
for (int j = 0; j < 3; ++ j) {
|
||||
int neighbor_idx = this->stl.neighbors_start[facet_idx].neighbor[j];
|
||||
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx])
|
||||
facet_queue[facet_queue_cnt ++] = neighbor_idx;
|
||||
}
|
||||
}
|
||||
|
||||
// If any of the face was not visited at the first time, return "multiple bodies".
|
||||
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx)
|
||||
if (! facet_visited[facet_idx])
|
||||
return true;
|
||||
return false;
|
||||
// Try finding an unvisited facet. If there are none, the mesh is not splittable.
|
||||
auto it = std::find(visited.begin(), visited.end(), false);
|
||||
return it != visited.end();
|
||||
}
|
||||
|
||||
size_t TriangleMesh::number_of_patches() const
|
||||
/**
|
||||
* Visit all unvisited neighboring facets that are reachable from the first unvisited facet,
|
||||
* and return them.
|
||||
*
|
||||
* @param facet_visited A reference to a vector of booleans. Contains whether or not a
|
||||
* facet with the same index has been visited.
|
||||
* @return A deque with all newly visited facets.
|
||||
*/
|
||||
std::deque<uint32_t> TriangleMesh::find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const
|
||||
{
|
||||
// we need neighbors
|
||||
// Make sure we're not operating on a broken mesh.
|
||||
if (!this->repaired)
|
||||
throw std::runtime_error("split() requires repair()");
|
||||
|
||||
if (this->stl.stats.number_of_facets == 0)
|
||||
return false;
|
||||
throw std::runtime_error("find_unvisited_neighbors() requires repair()");
|
||||
|
||||
std::vector<int> facet_queue(this->stl.stats.number_of_facets, 0);
|
||||
std::vector<char> facet_visited(this->stl.stats.number_of_facets, false);
|
||||
int facet_queue_cnt = 0;
|
||||
size_t num_bodies = 0;
|
||||
for (;;) {
|
||||
// Find a seeding triangle for a new body.
|
||||
int facet_idx = 0;
|
||||
for (; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx)
|
||||
if (! facet_visited[facet_idx]) {
|
||||
// A seed triangle was found.
|
||||
facet_queue[facet_queue_cnt ++] = facet_idx;
|
||||
facet_visited[facet_idx] = true;
|
||||
break;
|
||||
}
|
||||
if (facet_idx == this->stl.stats.number_of_facets)
|
||||
// No seed found.
|
||||
break;
|
||||
++ num_bodies;
|
||||
while (facet_queue_cnt > 0) {
|
||||
int facet_idx = facet_queue[-- facet_queue_cnt];
|
||||
facet_visited[facet_idx] = true;
|
||||
for (int j = 0; j < 3; ++ j) {
|
||||
int neighbor_idx = this->stl.neighbors_start[facet_idx].neighbor[j];
|
||||
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx])
|
||||
facet_queue[facet_queue_cnt ++] = neighbor_idx;
|
||||
}
|
||||
}
|
||||
// If the visited list is empty, populate it with false for every facet.
|
||||
if (facet_visited.empty())
|
||||
facet_visited = std::vector<unsigned char>(this->stl.stats.number_of_facets, false);
|
||||
|
||||
// Find the first unvisited facet.
|
||||
std::queue<uint32_t> facet_queue;
|
||||
std::deque<uint32_t> facets;
|
||||
auto facet = std::find(facet_visited.begin(), facet_visited.end(), false);
|
||||
if (facet != facet_visited.end()) {
|
||||
uint32_t idx = uint32_t(facet - facet_visited.begin());
|
||||
facet_queue.push(idx);
|
||||
facet_visited[idx] = true;
|
||||
facets.emplace_back(idx);
|
||||
}
|
||||
|
||||
return num_bodies;
|
||||
// Traverse all reachable neighbors and mark them as visited.
|
||||
while (! facet_queue.empty()) {
|
||||
uint32_t facet_idx = facet_queue.front();
|
||||
facet_queue.pop();
|
||||
for (int neighbor_idx : this->stl.neighbors_start[facet_idx].neighbor)
|
||||
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx]) {
|
||||
facet_queue.push(uint32_t(neighbor_idx));
|
||||
facet_visited[neighbor_idx] = true;
|
||||
facets.emplace_back(uint32_t(neighbor_idx));
|
||||
}
|
||||
}
|
||||
|
||||
return facets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a mesh into multiple meshes when possible.
|
||||
*
|
||||
* @return A TriangleMeshPtrs with the newly created meshes.
|
||||
*/
|
||||
TriangleMeshPtrs TriangleMesh::split() const
|
||||
{
|
||||
TriangleMeshPtrs meshes;
|
||||
std::vector<unsigned char> facet_visited(this->stl.stats.number_of_facets, false);
|
||||
|
||||
// we need neighbors
|
||||
if (!this->repaired)
|
||||
throw std::runtime_error("split() requires repair()");
|
||||
|
||||
// loop while we have remaining facets
|
||||
// Loop while we have remaining facets.
|
||||
std::vector<unsigned char> facet_visited;
|
||||
TriangleMeshPtrs meshes;
|
||||
for (;;) {
|
||||
// get the first facet
|
||||
std::queue<int> facet_queue;
|
||||
std::deque<int> facets;
|
||||
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx) {
|
||||
if (! facet_visited[facet_idx]) {
|
||||
// if facet was not seen put it into queue and start searching
|
||||
facet_queue.push(facet_idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (facet_queue.empty())
|
||||
std::deque<uint32_t> facets = find_unvisited_neighbors(facet_visited);
|
||||
if (facets.empty())
|
||||
break;
|
||||
|
||||
while (! facet_queue.empty()) {
|
||||
int facet_idx = facet_queue.front();
|
||||
facet_queue.pop();
|
||||
if (! facet_visited[facet_idx]) {
|
||||
facets.emplace_back(facet_idx);
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]);
|
||||
facet_visited[facet_idx] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new mesh for the part that was just split off.
|
||||
TriangleMesh* mesh = new TriangleMesh;
|
||||
meshes.emplace_back(mesh);
|
||||
mesh->stl.stats.type = inmemory;
|
||||
|
|
@ -452,14 +428,15 @@ TriangleMeshPtrs TriangleMesh::split() const
|
|||
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
|
||||
stl_clear_error(&mesh->stl);
|
||||
stl_allocate(&mesh->stl);
|
||||
|
||||
|
||||
// Assign the facets to the new mesh.
|
||||
bool first = true;
|
||||
for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++ facet) {
|
||||
for (auto facet = facets.begin(); facet != facets.end(); ++ facet) {
|
||||
mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet];
|
||||
stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return meshes;
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +453,7 @@ void TriangleMesh::merge(const TriangleMesh &mesh)
|
|||
stl_reallocate(&this->stl);
|
||||
|
||||
// copy facets
|
||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i)
|
||||
for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++ i)
|
||||
this->stl.facet_start[number_of_facets + i] = mesh.stl.facet_start[i];
|
||||
|
||||
// update size
|
||||
|
|
@ -489,7 +466,7 @@ ExPolygons TriangleMesh::horizontal_projection() const
|
|||
{
|
||||
Polygons pp;
|
||||
pp.reserve(this->stl.stats.number_of_facets);
|
||||
for (int i = 0; i < this->stl.stats.number_of_facets; ++ i) {
|
||||
for (uint32_t i = 0; i < this->stl.stats.number_of_facets; ++ i) {
|
||||
stl_facet* facet = &this->stl.facet_start[i];
|
||||
Polygon p;
|
||||
p.points.resize(3);
|
||||
|
|
@ -531,7 +508,7 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) c
|
|||
BoundingBoxf3 bbox;
|
||||
if (stl.v_shared == nullptr) {
|
||||
// Using the STL faces.
|
||||
for (int i = 0; i < this->facets_count(); ++ i) {
|
||||
for (size_t i = 0; i < this->facets_count(); ++ i) {
|
||||
const stl_facet &facet = this->stl.facet_start[i];
|
||||
for (size_t j = 0; j < 3; ++ j)
|
||||
bbox.merge(trafo * facet.vertex[j].cast<double>());
|
||||
|
|
@ -656,7 +633,7 @@ void TriangleMeshSlicer::init(TriangleMesh *_mesh, throw_on_cancel_callback_type
|
|||
};
|
||||
std::vector<EdgeToFace> edges_map;
|
||||
edges_map.assign(this->mesh->stl.stats.number_of_facets * 3, EdgeToFace());
|
||||
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
|
||||
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
|
||||
for (int i = 0; i < 3; ++ i) {
|
||||
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
||||
e2f.vertex_low = this->mesh->stl.v_indices[facet_idx].vertex[i];
|
||||
|
|
@ -905,7 +882,6 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
|
|||
const stl_normal &normal = this->mesh->stl.facet_start[facet_idx].normal;
|
||||
// We may ignore this edge for slicing purposes, but we may still use it for object cutting.
|
||||
FacetSliceType result = Slicing;
|
||||
const stl_neighbors &nbr = this->mesh->stl.neighbors_start[facet_idx];
|
||||
if (min_z == max_z) {
|
||||
// All three vertices are aligned with slice_z.
|
||||
line_out->edge_type = feHorizontal;
|
||||
|
|
@ -917,8 +893,6 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
|
|||
}
|
||||
} else {
|
||||
// Two vertices are aligned with the cutting plane, the third vertex is below or above the cutting plane.
|
||||
int nbr_idx = j % 3;
|
||||
int nbr_face = nbr.neighbor[nbr_idx];
|
||||
// Is the third vertex below the cutting plane?
|
||||
bool third_below = v0.z() < slice_z || v1.z() < slice_z || v2.z() < slice_z;
|
||||
// Two vertices on the cutting plane, the third vertex is below the plane. Consider the edge to be part of the slice
|
||||
|
|
@ -1697,7 +1671,7 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
|
|||
|
||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object";
|
||||
float scaled_z = scale_(z);
|
||||
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
|
||||
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
|
||||
stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
|
||||
|
||||
// find facet extents
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
void scale(float factor);
|
||||
void scale(const Vec3d &versor);
|
||||
void translate(float x, float y, float z);
|
||||
void translate(const Vec3f &displacement);
|
||||
void rotate(float angle, const Axis &axis);
|
||||
void rotate(float angle, const Vec3d& axis);
|
||||
void rotate_x(float angle) { this->rotate(angle, X); }
|
||||
|
|
@ -49,7 +50,7 @@ public:
|
|||
void mirror_x() { this->mirror(X); }
|
||||
void mirror_y() { this->mirror(Y); }
|
||||
void mirror_z() { this->mirror(Z); }
|
||||
void transform(const Transform3d& t);
|
||||
void transform(const Transform3d& t, bool fix_left_handed = false);
|
||||
void align_to_origin();
|
||||
void rotate(double angle, Point* center);
|
||||
TriangleMeshPtrs split() const;
|
||||
|
|
@ -68,18 +69,14 @@ public:
|
|||
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
||||
bool empty() const { return this->facets_count() == 0; }
|
||||
|
||||
// Returns true, if there are two and more connected patches in the mesh.
|
||||
// Returns false, if one or zero connected patch is in the mesh.
|
||||
bool has_multiple_patches() const;
|
||||
|
||||
// Count disconnected triangle patches.
|
||||
size_t number_of_patches() const;
|
||||
bool is_splittable() const;
|
||||
|
||||
stl_file stl;
|
||||
bool repaired;
|
||||
|
||||
private:
|
||||
void require_shared_vertices();
|
||||
std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const;
|
||||
friend class TriangleMeshSlicer;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ public:
|
|||
|
||||
// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes
|
||||
// and removing spaces.
|
||||
static std::string short_time(const std::string &time)
|
||||
inline std::string short_time(const std::string &time)
|
||||
{
|
||||
// Parse the dhms time format.
|
||||
int days = 0;
|
||||
|
|
@ -247,7 +247,7 @@ static std::string short_time(const std::string &time)
|
|||
}
|
||||
|
||||
// Returns the given time is seconds in format DDd HHh MMm SSs
|
||||
static std::string get_time_dhms(float time_in_secs)
|
||||
inline std::string get_time_dhms(float time_in_secs)
|
||||
{
|
||||
int days = (int)(time_in_secs / 86400.0f);
|
||||
time_in_secs -= (float)days * 86400.0f;
|
||||
|
|
|
|||
223
src/libslic3r/Zipper.cpp
Normal file
223
src/libslic3r/Zipper.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Zipper.hpp"
|
||||
#include "miniz/miniz_zip.h"
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "I18N.hpp"
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800 || __cplusplus < 201103L
|
||||
#define SLIC3R_NORETURN
|
||||
#elif __cplusplus >= 201103L
|
||||
#define SLIC3R_NORETURN [[noreturn]]
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Zipper::Impl {
|
||||
public:
|
||||
mz_zip_archive arch;
|
||||
std::string m_zipname;
|
||||
|
||||
static std::string get_errorstr(mz_zip_error mz_err)
|
||||
{
|
||||
switch (mz_err)
|
||||
{
|
||||
case MZ_ZIP_NO_ERROR:
|
||||
return "no error";
|
||||
case MZ_ZIP_UNDEFINED_ERROR:
|
||||
return L("undefined error");
|
||||
case MZ_ZIP_TOO_MANY_FILES:
|
||||
return L("too many files");
|
||||
case MZ_ZIP_FILE_TOO_LARGE:
|
||||
return L("file too large");
|
||||
case MZ_ZIP_UNSUPPORTED_METHOD:
|
||||
return L("unsupported method");
|
||||
case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
|
||||
return L("unsupported encryption");
|
||||
case MZ_ZIP_UNSUPPORTED_FEATURE:
|
||||
return L("unsupported feature");
|
||||
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
|
||||
return L("failed finding central directory");
|
||||
case MZ_ZIP_NOT_AN_ARCHIVE:
|
||||
return L("not a ZIP archive");
|
||||
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
|
||||
return L("invalid header or archive is corrupted");
|
||||
case MZ_ZIP_UNSUPPORTED_MULTIDISK:
|
||||
return L("unsupported multidisk archive");
|
||||
case MZ_ZIP_DECOMPRESSION_FAILED:
|
||||
return L("decompression failed or archive is corrupted");
|
||||
case MZ_ZIP_COMPRESSION_FAILED:
|
||||
return L("compression failed");
|
||||
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
|
||||
return L("unexpected decompressed size");
|
||||
case MZ_ZIP_CRC_CHECK_FAILED:
|
||||
return L("CRC-32 check failed");
|
||||
case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
|
||||
return L("unsupported central directory size");
|
||||
case MZ_ZIP_ALLOC_FAILED:
|
||||
return L("allocation failed");
|
||||
case MZ_ZIP_FILE_OPEN_FAILED:
|
||||
return L("file open failed");
|
||||
case MZ_ZIP_FILE_CREATE_FAILED:
|
||||
return L("file create failed");
|
||||
case MZ_ZIP_FILE_WRITE_FAILED:
|
||||
return L("file write failed");
|
||||
case MZ_ZIP_FILE_READ_FAILED:
|
||||
return L("file read failed");
|
||||
case MZ_ZIP_FILE_CLOSE_FAILED:
|
||||
return L("file close failed");
|
||||
case MZ_ZIP_FILE_SEEK_FAILED:
|
||||
return L("file seek failed");
|
||||
case MZ_ZIP_FILE_STAT_FAILED:
|
||||
return L("file stat failed");
|
||||
case MZ_ZIP_INVALID_PARAMETER:
|
||||
return L("invalid parameter");
|
||||
case MZ_ZIP_INVALID_FILENAME:
|
||||
return L("invalid filename");
|
||||
case MZ_ZIP_BUF_TOO_SMALL:
|
||||
return L("buffer too small");
|
||||
case MZ_ZIP_INTERNAL_ERROR:
|
||||
return L("internal error");
|
||||
case MZ_ZIP_FILE_NOT_FOUND:
|
||||
return L("file not found");
|
||||
case MZ_ZIP_ARCHIVE_TOO_LARGE:
|
||||
return L("archive is too large");
|
||||
case MZ_ZIP_VALIDATION_FAILED:
|
||||
return L("validation failed");
|
||||
case MZ_ZIP_WRITE_CALLBACK_FAILED:
|
||||
return L("write calledback failed");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
std::string formatted_errorstr() const
|
||||
{
|
||||
return L("Error with zip archive") + " " + m_zipname + ": " +
|
||||
get_errorstr(arch.m_last_error) + "!";
|
||||
}
|
||||
|
||||
SLIC3R_NORETURN void blow_up() const
|
||||
{
|
||||
throw std::runtime_error(formatted_errorstr());
|
||||
}
|
||||
|
||||
bool is_alive()
|
||||
{
|
||||
return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
|
||||
}
|
||||
};
|
||||
|
||||
Zipper::Zipper(const std::string &zipfname, e_compression compression)
|
||||
{
|
||||
m_impl.reset(new Impl());
|
||||
|
||||
m_compression = compression;
|
||||
m_impl->m_zipname = zipfname;
|
||||
|
||||
memset(&m_impl->arch, 0, sizeof(m_impl->arch));
|
||||
|
||||
// Initialize the archive data
|
||||
if(!mz_zip_writer_init_file(&m_impl->arch, zipfname.c_str(), 0))
|
||||
m_impl->blow_up();
|
||||
}
|
||||
|
||||
Zipper::~Zipper()
|
||||
{
|
||||
if(m_impl->is_alive()) {
|
||||
// Flush the current entry if not finished yet.
|
||||
try { finish_entry(); } catch(...) {
|
||||
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
|
||||
}
|
||||
|
||||
if(!mz_zip_writer_finalize_archive(&m_impl->arch))
|
||||
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
|
||||
}
|
||||
|
||||
// The file should be closed no matter what...
|
||||
if(!mz_zip_writer_end(&m_impl->arch))
|
||||
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
|
||||
}
|
||||
|
||||
Zipper::Zipper(Zipper &&m):
|
||||
m_impl(std::move(m.m_impl)),
|
||||
m_data(std::move(m.m_data)),
|
||||
m_entry(std::move(m.m_entry)),
|
||||
m_compression(m.m_compression) {}
|
||||
|
||||
Zipper &Zipper::operator=(Zipper &&m) {
|
||||
m_impl = std::move(m.m_impl);
|
||||
m_data = std::move(m.m_data);
|
||||
m_entry = std::move(m.m_entry);
|
||||
m_compression = m.m_compression;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Zipper::add_entry(const std::string &name)
|
||||
{
|
||||
if(!m_impl->is_alive()) return;
|
||||
|
||||
finish_entry(); // finish previous business
|
||||
m_entry = name;
|
||||
}
|
||||
|
||||
void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
|
||||
{
|
||||
if(!m_impl->is_alive()) return;
|
||||
|
||||
finish_entry();
|
||||
mz_uint cmpr = MZ_NO_COMPRESSION;
|
||||
switch (m_compression) {
|
||||
case NO_COMPRESSION: cmpr = MZ_NO_COMPRESSION; break;
|
||||
case FAST_COMPRESSION: cmpr = MZ_BEST_SPEED; break;
|
||||
case TIGHT_COMPRESSION: cmpr = MZ_BEST_COMPRESSION; break;
|
||||
}
|
||||
|
||||
if(!mz_zip_writer_add_mem(&m_impl->arch, name.c_str(), data, l, cmpr))
|
||||
m_impl->blow_up();
|
||||
|
||||
m_entry.clear();
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
void Zipper::finish_entry()
|
||||
{
|
||||
if(!m_impl->is_alive()) return;
|
||||
|
||||
if(!m_data.empty() && !m_entry.empty()) {
|
||||
mz_uint compression = MZ_NO_COMPRESSION;
|
||||
|
||||
switch (m_compression) {
|
||||
case NO_COMPRESSION: compression = MZ_NO_COMPRESSION; break;
|
||||
case FAST_COMPRESSION: compression = MZ_BEST_SPEED; break;
|
||||
case TIGHT_COMPRESSION: compression = MZ_BEST_COMPRESSION; break;
|
||||
}
|
||||
|
||||
if(!mz_zip_writer_add_mem(&m_impl->arch, m_entry.c_str(),
|
||||
m_data.c_str(),
|
||||
m_data.size(),
|
||||
compression)) m_impl->blow_up();
|
||||
}
|
||||
|
||||
m_data.clear();
|
||||
m_entry.clear();
|
||||
}
|
||||
|
||||
void Zipper::finalize()
|
||||
{
|
||||
finish_entry();
|
||||
|
||||
if(m_impl->is_alive()) if(!mz_zip_writer_finalize_archive(&m_impl->arch))
|
||||
m_impl->blow_up();
|
||||
}
|
||||
|
||||
}
|
||||
90
src/libslic3r/Zipper.hpp
Normal file
90
src/libslic3r/Zipper.hpp
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef ZIPPER_HPP
|
||||
#define ZIPPER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Class for creating zip archives.
|
||||
class Zipper {
|
||||
public:
|
||||
// Three compression levels supported
|
||||
enum e_compression {
|
||||
NO_COMPRESSION,
|
||||
FAST_COMPRESSION,
|
||||
TIGHT_COMPRESSION
|
||||
};
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
std::string m_data;
|
||||
std::string m_entry;
|
||||
e_compression m_compression;
|
||||
|
||||
public:
|
||||
|
||||
// Will blow up in a runtime exception if the file cannot be created.
|
||||
explicit Zipper(const std::string& zipfname,
|
||||
e_compression level = NO_COMPRESSION);
|
||||
~Zipper();
|
||||
|
||||
// No copies allwed, this is a file resource...
|
||||
Zipper(const Zipper&) = delete;
|
||||
Zipper& operator=(const Zipper&) = delete;
|
||||
|
||||
// Moving is fine.
|
||||
// Zipper(Zipper&&) = default;
|
||||
// Zipper& operator=(Zipper&&) = default;
|
||||
// All becouse of VS2013:
|
||||
Zipper(Zipper &&m);
|
||||
Zipper& operator=(Zipper &&m);
|
||||
|
||||
/// Adding an entry means a file inside the new archive. Name param is the
|
||||
/// name of the new file. To create directories, append a forward slash.
|
||||
/// The previous entry is finished (see finish_entry)
|
||||
void add_entry(const std::string& name);
|
||||
|
||||
/// Add a new binary file entry with an instantly given byte buffer.
|
||||
/// This method throws exactly like finish_entry() does.
|
||||
void add_entry(const std::string& name, const std::uint8_t* data, size_t l);
|
||||
|
||||
// Writing data to the archive works like with standard streams. The target
|
||||
// within the zip file is the entry created with the add_entry method.
|
||||
|
||||
// Template taking only arithmetic values, that std::to_string can handle.
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, Zipper&>::type
|
||||
operator<<(T &&val) {
|
||||
return this->operator<<(std::to_string(std::forward<T>(val)));
|
||||
}
|
||||
|
||||
// Template applied only for types that std::string can handle for append
|
||||
// and copy. This includes c style strings...
|
||||
template<class T> inline
|
||||
typename std::enable_if<!std::is_arithmetic<T>::value, Zipper&>::type
|
||||
operator<<(T &&val) {
|
||||
if(m_data.empty()) m_data = std::forward<T>(val);
|
||||
else m_data.append(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Finishing an entry means that subsequent writes will no longer be
|
||||
/// appended to the previous entry. They will be written into the internal
|
||||
/// buffer and ones an entry is added, the buffer will bind to the new entry
|
||||
/// If the buffer was written, but no entry was added, the buffer will be
|
||||
/// cleared after this call.
|
||||
///
|
||||
/// This method will throw a runtime exception if an error occures. The
|
||||
/// entry will still be open (with the data intact) but the state of the
|
||||
/// file is up to minz after the erroneous write.
|
||||
void finish_entry();
|
||||
|
||||
void finalize();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // ZIPPER_HPP
|
||||
|
|
@ -2897,6 +2897,8 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
|
|
@ -2904,8 +2906,8 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
|
|||
char* data = NULL;
|
||||
NSVGimage* image = NULL;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) goto error;
|
||||
fp = boost::nowide::fopen(filename, "rb");
|
||||
if (!fp) goto error;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
png++ is written by Alexander Shulgin (alex dot shulgin at gmail dot com)
|
||||
Copyright (C) 2007,2008
|
||||
|
||||
When writing to me be sure to put png++: in the subject :-)
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
Copying png++ is subject to the following license:
|
||||
|
||||
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 AUTHOR ``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 AUTHOR 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.
|
||||
60
src/png/NEWS
60
src/png/NEWS
|
|
@ -1,60 +0,0 @@
|
|||
Version 0.2.7:
|
||||
|
||||
- Added solid_pixel_buffer (patch by Andrey Potapov).
|
||||
|
||||
- Fixed some compilation problems on Win32.
|
||||
|
||||
Version 0.2.5:
|
||||
|
||||
- Fixed compatibility with newer libpng versions (>= 1.4)
|
||||
|
||||
- Fixed compilation on FreeBSD.
|
||||
|
||||
- Fixed tRNS handling with transformations.
|
||||
|
||||
- Added IO transformation debugging facility.
|
||||
|
||||
- Better organized test suite.
|
||||
|
||||
Version 0.2.3:
|
||||
|
||||
- Fixed numerous `already defined' errors due to require_color_space
|
||||
implementation.
|
||||
|
||||
- Added `config.hpp'.
|
||||
|
||||
- Fixed `strerror' usage.
|
||||
|
||||
- Minor docs fixes.
|
||||
|
||||
|
||||
Version 0.2.1:
|
||||
|
||||
- Added support for tRNS chunk.
|
||||
|
||||
- Added non-std IO streams support.
|
||||
|
||||
- Fixed 16-bit endianness problems.
|
||||
|
||||
- Improved test script.
|
||||
|
||||
|
||||
Version 0.2.0:
|
||||
|
||||
- Added support for 16-bit data (RGB, RGBA, Grayscale and Gray+Alpha
|
||||
color types)
|
||||
|
||||
- Added support for packed 1-, 2- or 4-bit pixels (Grayscale and
|
||||
Indexed colors)
|
||||
|
||||
- Fixed interlace handling code which was severely broken
|
||||
|
||||
- Added possibility to process images without reading the entire
|
||||
image into memory
|
||||
|
||||
- Internals are refactored while the client interface is mostly
|
||||
unchanged
|
||||
|
||||
- Added intensive test suite
|
||||
|
||||
- Added documentation
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_COLOR_HPP_INCLUDED
|
||||
#define PNGPP_COLOR_HPP_INCLUDED
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief PNG color struct extension. Adds constructors.
|
||||
*/
|
||||
struct color
|
||||
: png_color
|
||||
{
|
||||
explicit color(byte r = 0, byte g = 0, byte b = 0)
|
||||
{
|
||||
this->red = r;
|
||||
this->green = g;
|
||||
this->blue = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initializes color with a copy of png_color object.
|
||||
*/
|
||||
color(png_color const& other)
|
||||
{
|
||||
this->red = other.red;
|
||||
this->green = other.green;
|
||||
this->blue = other.blue;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_COLOR_HPP_INCLUDED
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_END_INFO_HPP_INCLUDED
|
||||
#define PNGPP_END_INFO_HPP_INCLUDED
|
||||
|
||||
#include "info_base.hpp"
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Internal class to hold PNG ending %info.
|
||||
*
|
||||
* \see info, info_base
|
||||
*/
|
||||
class end_info
|
||||
: public info_base
|
||||
{
|
||||
public:
|
||||
end_info(io_base& io, png_struct* png)
|
||||
: info_base(io, png)
|
||||
{
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
assert(m_info);
|
||||
png_destroy_info_struct(m_png, & m_info);
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
png_read_end(m_png, m_info);
|
||||
}
|
||||
|
||||
void write() const
|
||||
{
|
||||
png_write_end(m_png, m_info);
|
||||
}
|
||||
|
||||
// TODO: add methods to read/write text comments etc.
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_END_INFO_HPP_INCLUDED
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_ERROR_HPP_INCLUDED
|
||||
#define PNGPP_ERROR_HPP_INCLUDED
|
||||
|
||||
/* check if we have strerror_s or strerror_r, prefer the former which is C11 std */
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <string.h>
|
||||
|
||||
#define HAVE_STRERROR_S 1
|
||||
#else
|
||||
#undef HAVE_STRERROR_S
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Exception class to represent runtime errors related to
|
||||
* png++ operation.
|
||||
*/
|
||||
class error
|
||||
: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \param message error description
|
||||
*/
|
||||
explicit error(std::string const& message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception class to represent standard library errors
|
||||
* (generally IO).
|
||||
*
|
||||
* \see reader, writer
|
||||
*/
|
||||
class std_error
|
||||
: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs an std_error object. The \a message string is
|
||||
* appended with <tt>": "</tt> and the error description as
|
||||
* returned by \c strerror(\a error).
|
||||
*
|
||||
* \param message error description
|
||||
* \param error error number
|
||||
*/
|
||||
explicit std_error(std::string const& message, int errnum = errno)
|
||||
: std::runtime_error((message + ": ") + thread_safe_strerror(errnum))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::string thread_safe_strerror(int errnum)
|
||||
{
|
||||
#define ERRBUF_SIZE 512
|
||||
|
||||
#ifdef HAVE_STRERROR_S
|
||||
char buf[ERRBUF_SIZE] = { 0 };
|
||||
strerror_s(buf, ERRBUF_SIZE, errnum);
|
||||
return std::string(buf);
|
||||
#else
|
||||
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
|
||||
char buf[ERRBUF_SIZE] = { 0 };
|
||||
strerror_r(errnum, buf, ERRBUF_SIZE);
|
||||
return std::string(buf);
|
||||
#elif _GNU_SOURCE
|
||||
/* GNU variant can return a pointer to static buffer instead of buf */
|
||||
char buf[ERRBUF_SIZE] = { 0 };
|
||||
return std::string(strerror_r(errnum, buf, ERRBUF_SIZE));
|
||||
#else
|
||||
return std::string("An error occured with errnum ") +
|
||||
std::to_string(errnum) +
|
||||
". Converting to the appropriate error message is disabled"
|
||||
"in this instance of the png++ library.";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef ERRBUF_SIZE
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_ERROR_HPP_INCLUDED
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_IMAGE_INFO_HPP_INCLUDED
|
||||
#define PNGPP_IMAGE_INFO_HPP_INCLUDED
|
||||
|
||||
#include "types.hpp"
|
||||
#include "palette.hpp"
|
||||
#include "tRNS.hpp"
|
||||
#include "pixel_traits.hpp"
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Holds information about PNG image.
|
||||
*
|
||||
* \see image, generator, consumer
|
||||
*/
|
||||
class image_info
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Constructs the image_info object with default values
|
||||
* for color_type, interlace_type, compression_method and
|
||||
* filter_type.
|
||||
*/
|
||||
image_info()
|
||||
: m_width(0),
|
||||
m_height(0),
|
||||
m_bit_depth(0),
|
||||
m_color_type(color_type_none),
|
||||
m_interlace_type(interlace_none),
|
||||
m_compression_type(compression_type_default),
|
||||
m_filter_type(filter_type_default),
|
||||
m_gamma(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
uint_32 get_width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
void set_width(uint_32 width)
|
||||
{
|
||||
m_width = width;
|
||||
}
|
||||
|
||||
uint_32 get_height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void set_height(uint_32 height)
|
||||
{
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
color_type get_color_type() const
|
||||
{
|
||||
return m_color_type;
|
||||
}
|
||||
|
||||
void set_color_type(color_type color_space)
|
||||
{
|
||||
m_color_type = color_space;
|
||||
}
|
||||
|
||||
int get_bit_depth() const
|
||||
{
|
||||
return m_bit_depth;
|
||||
}
|
||||
|
||||
void set_bit_depth(int bit_depth)
|
||||
{
|
||||
m_bit_depth = bit_depth;
|
||||
}
|
||||
|
||||
interlace_type get_interlace_type() const
|
||||
{
|
||||
return m_interlace_type;
|
||||
}
|
||||
|
||||
void set_interlace_type(interlace_type interlace)
|
||||
{
|
||||
m_interlace_type = interlace;
|
||||
}
|
||||
|
||||
compression_type get_compression_type() const
|
||||
{
|
||||
return m_compression_type;
|
||||
}
|
||||
|
||||
void set_compression_type(compression_type compression)
|
||||
{
|
||||
m_compression_type = compression;
|
||||
}
|
||||
|
||||
filter_type get_filter_type() const
|
||||
{
|
||||
return m_filter_type;
|
||||
}
|
||||
|
||||
void set_filter_type(filter_type filter)
|
||||
{
|
||||
m_filter_type = filter;
|
||||
}
|
||||
|
||||
palette const& get_palette() const
|
||||
{
|
||||
return m_palette;
|
||||
}
|
||||
|
||||
palette& get_palette()
|
||||
{
|
||||
return m_palette;
|
||||
}
|
||||
|
||||
void set_palette(palette const& plte)
|
||||
{
|
||||
m_palette = plte;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Removes all entries from the palette.
|
||||
*/
|
||||
void drop_palette()
|
||||
{
|
||||
m_palette.clear();
|
||||
}
|
||||
|
||||
tRNS const& get_tRNS() const
|
||||
{
|
||||
return m_tRNS;
|
||||
}
|
||||
|
||||
tRNS& get_tRNS()
|
||||
{
|
||||
return m_tRNS;
|
||||
}
|
||||
|
||||
void set_tRNS(tRNS const& trns)
|
||||
{
|
||||
m_tRNS = trns;
|
||||
}
|
||||
|
||||
double get_gamma() const
|
||||
{
|
||||
return m_gamma;
|
||||
}
|
||||
|
||||
void set_gamma(double gamma)
|
||||
{
|
||||
m_gamma = gamma;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint_32 m_width;
|
||||
uint_32 m_height;
|
||||
int m_bit_depth;
|
||||
color_type m_color_type;
|
||||
interlace_type m_interlace_type;
|
||||
compression_type m_compression_type;
|
||||
filter_type m_filter_type;
|
||||
palette m_palette;
|
||||
tRNS m_tRNS;
|
||||
double m_gamma;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns an image_info object with color_type and
|
||||
* bit_depth fields setup appropriate for the \c pixel type.
|
||||
*/
|
||||
template< typename pixel >
|
||||
image_info
|
||||
make_image_info()
|
||||
{
|
||||
typedef pixel_traits< pixel > traits;
|
||||
image_info info;
|
||||
info.set_color_type(traits::get_color_type());
|
||||
info.set_bit_depth(traits::get_bit_depth());
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_IMAGE_INFO_HPP_INCLUDED
|
||||
186
src/png/info.hpp
186
src/png/info.hpp
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_INFO_HPP_INCLUDED
|
||||
#define PNGPP_INFO_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include "info_base.hpp"
|
||||
#include "image_info.hpp"
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Holds information about PNG image. Adapter class for IO
|
||||
* image operations.
|
||||
*/
|
||||
class info
|
||||
: public info_base,
|
||||
public image_info
|
||||
{
|
||||
public:
|
||||
info(io_base& io, png_struct* png)
|
||||
: info_base(io, png)
|
||||
{
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
assert(m_png);
|
||||
assert(m_info);
|
||||
|
||||
png_read_info(m_png, m_info);
|
||||
png_get_IHDR(m_png,
|
||||
m_info,
|
||||
& m_width,
|
||||
& m_height,
|
||||
reinterpret_cast< int* >(& m_bit_depth),
|
||||
reinterpret_cast< int* >(& m_color_type),
|
||||
reinterpret_cast< int* >(& m_interlace_type),
|
||||
reinterpret_cast< int* >(& m_compression_type),
|
||||
reinterpret_cast< int* >(& m_filter_type));
|
||||
|
||||
if (png_get_valid(m_png, m_info, chunk_PLTE) == chunk_PLTE)
|
||||
{
|
||||
png_color* colors = 0;
|
||||
int count = 0;
|
||||
png_get_PLTE(m_png, m_info, & colors, & count);
|
||||
m_palette.assign(colors, colors + count);
|
||||
}
|
||||
|
||||
#ifdef PNG_tRNS_SUPPORTED
|
||||
if (png_get_valid(m_png, m_info, chunk_tRNS) == chunk_tRNS)
|
||||
{
|
||||
if (m_color_type == color_type_palette)
|
||||
{
|
||||
int count;
|
||||
byte* values;
|
||||
if (png_get_tRNS(m_png, m_info, & values, & count, NULL)
|
||||
!= PNG_INFO_tRNS)
|
||||
{
|
||||
throw error("png_get_tRNS() failed");
|
||||
}
|
||||
m_tRNS.assign(values, values + count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_gAMA_SUPPORTED
|
||||
if (png_get_valid(m_png, m_info, chunk_gAMA) == chunk_gAMA)
|
||||
{
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
if (png_get_gAMA(m_png, m_info, &m_gamma) != PNG_INFO_gAMA)
|
||||
{
|
||||
throw error("png_get_gAMA() failed");
|
||||
}
|
||||
#else
|
||||
png_fixed_point gamma = 0;
|
||||
if (png_get_gAMA_fixed(m_png, m_info, &gamma) != PNG_INFO_gAMA)
|
||||
{
|
||||
throw error("png_get_gAMA_fixed() failed");
|
||||
}
|
||||
m_gamma = gamma / 100000.0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void write() const
|
||||
{
|
||||
assert(m_png);
|
||||
assert(m_info);
|
||||
|
||||
sync_ihdr();
|
||||
if (m_color_type == color_type_palette)
|
||||
{
|
||||
if (! m_palette.empty())
|
||||
{
|
||||
png_set_PLTE(m_png, m_info,
|
||||
const_cast< color* >(& m_palette[0]),
|
||||
(int) m_palette.size());
|
||||
}
|
||||
if (! m_tRNS.empty())
|
||||
{
|
||||
#ifdef PNG_tRNS_SUPPORTED
|
||||
png_set_tRNS(m_png, m_info,
|
||||
const_cast< byte* >(& m_tRNS[0]),
|
||||
m_tRNS.size(),
|
||||
NULL);
|
||||
#else
|
||||
throw error("attempted to write tRNS chunk; recompile with PNG_tRNS_SUPPORTED");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (m_gamma > 0)
|
||||
{
|
||||
#ifdef PNG_gAMA_SUPPORTED
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_set_gAMA(m_png, m_info, m_gamma);
|
||||
#else
|
||||
png_set_gAMA_fixed(m_png, m_info,
|
||||
(png_fixed_point)(m_gamma * 100000));
|
||||
#endif
|
||||
#else
|
||||
throw error("attempted to write gAMA chunk; recompile with PNG_gAMA_SUPPORTED");
|
||||
#endif
|
||||
}
|
||||
|
||||
png_write_info(m_png, m_info);
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
assert(m_png);
|
||||
assert(m_info);
|
||||
|
||||
sync_ihdr();
|
||||
png_read_update_info(m_png, m_info);
|
||||
}
|
||||
|
||||
protected:
|
||||
void sync_ihdr(void) const
|
||||
{
|
||||
png_set_IHDR(m_png,
|
||||
m_info,
|
||||
m_width,
|
||||
m_height,
|
||||
m_bit_depth,
|
||||
m_color_type,
|
||||
m_interlace_type,
|
||||
m_compression_type,
|
||||
m_filter_type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_INFO_HPP_INCLUDED
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_INFO_BASE_HPP_INCLUDED
|
||||
#define PNGPP_INFO_BASE_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include "error.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
class io_base;
|
||||
|
||||
/**
|
||||
* \brief Internal class to hold PNG info or end_info.
|
||||
*/
|
||||
class info_base
|
||||
{
|
||||
info_base(info_base const&);
|
||||
info_base& operator=(info_base const&);
|
||||
|
||||
public:
|
||||
info_base(io_base& io, png_struct* png)
|
||||
: m_io(io),
|
||||
m_png(png),
|
||||
m_info(png_create_info_struct(m_png))
|
||||
{
|
||||
}
|
||||
|
||||
png_info* get_png_info() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
png_info** get_png_info_ptr()
|
||||
{
|
||||
return & m_info;
|
||||
}
|
||||
|
||||
protected:
|
||||
io_base& m_io;
|
||||
png_struct* m_png;
|
||||
png_info* m_info;
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_INFO_BASE_HPP_INCLUDED
|
||||
|
|
@ -1,467 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Alex Shulgin
|
||||
*
|
||||
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
|
||||
* software; the exact copying conditions are as follows:
|
||||
*
|
||||
* 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 AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef PNGPP_IO_BASE_HPP_INCLUDED
|
||||
#define PNGPP_IO_BASE_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include "error.hpp"
|
||||
#include "info.hpp"
|
||||
#include "end_info.hpp"
|
||||
|
||||
static void
|
||||
trace_io_transform(char const* fmt, ...)
|
||||
{
|
||||
#ifdef DEBUG_IO_TRANSFORM
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "TRANSFORM_IO: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
#define TRACE_IO_TRANSFORM trace_io_transform
|
||||
|
||||
namespace png
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Base class for PNG reader/writer classes.
|
||||
*
|
||||
* \see reader, writer
|
||||
*/
|
||||
class io_base
|
||||
{
|
||||
io_base(io_base const&);
|
||||
io_base& operator=(io_base const&);
|
||||
|
||||
public:
|
||||
explicit io_base(png_struct* png)
|
||||
: m_png(png),
|
||||
m_info(*this, m_png),
|
||||
m_end_info(*this, m_png)
|
||||
{
|
||||
}
|
||||
|
||||
~io_base()
|
||||
{
|
||||
assert(! m_png);
|
||||
assert(! m_info.get_png_info());
|
||||
assert(! m_end_info.get_png_info());
|
||||
}
|
||||
|
||||
png_struct* get_png_struct() const
|
||||
{
|
||||
return m_png;
|
||||
}
|
||||
|
||||
info& get_info()
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
info const& get_info() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
image_info const& get_image_info() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
void set_image_info(image_info const& info)
|
||||
{
|
||||
static_cast< image_info& >(m_info) = info; // slice it
|
||||
}
|
||||
|
||||
end_info& get_end_info()
|
||||
{
|
||||
return m_end_info;
|
||||
}
|
||||
|
||||
end_info const& get_end_info() const
|
||||
{
|
||||
return m_end_info;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// info accessors
|
||||
//
|
||||
uint_32 get_width() const
|
||||
{
|
||||
return m_info.get_width();
|
||||
}
|
||||
|
||||
void set_width(uint_32 width)
|
||||
{
|
||||
m_info.set_width(width);
|
||||
}
|
||||
|
||||
uint_32 get_height() const
|
||||
{
|
||||
return m_info.get_height();
|
||||
}
|
||||
|
||||
void set_height(uint_32 height)
|
||||
{
|
||||
m_info.set_height(height);
|
||||
}
|
||||
|
||||
color_type get_color_type() const
|
||||
{
|
||||
return m_info.get_color_type();
|
||||
}
|
||||
|
||||
void set_color_type(color_type color_space)
|
||||
{
|
||||
m_info.set_color_type(color_space);
|
||||
}
|
||||
|
||||
int get_bit_depth() const
|
||||
{
|
||||
return m_info.get_bit_depth();
|
||||
}
|
||||
|
||||
void set_bit_depth(int bit_depth)
|
||||
{
|
||||
m_info.set_bit_depth(bit_depth);
|
||||
}
|
||||
|
||||
interlace_type get_interlace_type() const
|
||||
{
|
||||
return m_info.get_interlace_type();
|
||||
}
|
||||
|
||||
void set_interlace_type(interlace_type interlace)
|
||||
{
|
||||
m_info.set_interlace_type(interlace);
|
||||
}
|
||||
|
||||
compression_type get_compression_type() const
|
||||
{
|
||||
return m_info.get_compression_type();
|
||||
}
|
||||
|
||||
void set_compression_type(compression_type compression)
|
||||
{
|
||||
m_info.set_compression_type(compression);
|
||||
}
|
||||
|
||||
filter_type get_filter_type() const
|
||||
{
|
||||
return m_info.get_filter_type();
|
||||
}
|
||||
|
||||
void set_filter_type(filter_type filter)
|
||||
{
|
||||
m_info.set_filter_type(filter);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool has_chunk(chunk id)
|
||||
{
|
||||
return png_get_valid(m_png,
|
||||
m_info.get_png_info(),
|
||||
uint_32(id)) == uint_32(id);
|
||||
}
|
||||
|
||||
#if defined(PNG_READ_EXPAND_SUPPORTED)
|
||||
void set_gray_1_2_4_to_8() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_expand_gray_1_2_4_to_8\n");
|
||||
png_set_expand_gray_1_2_4_to_8(m_png);
|
||||
}
|
||||
|
||||
void set_palette_to_rgb() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_palette_to_rgb\n");
|
||||
png_set_palette_to_rgb(m_png);
|
||||
}
|
||||
|
||||
void set_tRNS_to_alpha() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_tRNS_to_alpha\n");
|
||||
png_set_tRNS_to_alpha(m_png);
|
||||
}
|
||||
#endif // defined(PNG_READ_EXPAND_SUPPORTED)
|
||||
|
||||
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
|
||||
void set_bgr() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_bgr\n");
|
||||
png_set_bgr(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
|
||||
void set_gray_to_rgb() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_gray_to_rgb\n");
|
||||
png_set_gray_to_rgb(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
void set_rgb_to_gray(rgb_to_gray_error_action error_action
|
||||
= rgb_to_gray_silent,
|
||||
double red_weight = -1.0,
|
||||
double green_weight = -1.0) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_rgb_to_gray: error_action=%d,"
|
||||
" red_weight=%lf, green_weight=%lf\n",
|
||||
error_action, red_weight, green_weight);
|
||||
|
||||
png_set_rgb_to_gray(m_png, error_action, red_weight, green_weight);
|
||||
}
|
||||
#else
|
||||
void set_rgb_to_gray(rgb_to_gray_error_action error_action
|
||||
= rgb_to_gray_silent,
|
||||
fixed_point red_weight = -1,
|
||||
fixed_point green_weight = -1) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_rgb_to_gray_fixed: error_action=%d,"
|
||||
" red_weight=%d, green_weight=%d\n",
|
||||
error_action, red_weight, green_weight);
|
||||
|
||||
png_set_rgb_to_gray_fixed(m_png, error_action,
|
||||
red_weight, green_weight);
|
||||
}
|
||||
#endif // PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// alpha channel transformations
|
||||
//
|
||||
#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
|
||||
void set_strip_alpha() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_strip_alpha\n");
|
||||
png_set_strip_alpha(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) \
|
||||
|| defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
|
||||
void set_swap_alpha() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_swap_alpha\n");
|
||||
png_set_swap_alpha(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) \
|
||||
|| defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
|
||||
void set_invert_alpha() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_invert_alpha\n");
|
||||
png_set_invert_alpha(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
|
||||
void set_filler(uint_32 filler, filler_type type) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_filler: filler=%08x, type=%d\n",
|
||||
filler, type);
|
||||
|
||||
png_set_filler(m_png, filler, type);
|
||||
}
|
||||
|
||||
#if !defined(PNG_1_0_X)
|
||||
void set_add_alpha(uint_32 filler, filler_type type) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_add_alpha: filler=%08x, type=%d\n",
|
||||
filler, type);
|
||||
|
||||
png_set_add_alpha(m_png, filler, type);
|
||||
}
|
||||
#endif
|
||||
#endif // PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED
|
||||
|
||||
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
void set_swap() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_swap\n");
|
||||
png_set_swap(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
|
||||
void set_packing() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_packing\n");
|
||||
png_set_packing(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED) \
|
||||
|| defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
void set_packswap() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_packswap\n");
|
||||
png_set_packswap(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
void set_shift(byte red_bits, byte green_bits, byte blue_bits,
|
||||
byte alpha_bits = 0) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_shift: red_bits=%d, green_bits=%d,"
|
||||
" blue_bits=%d, alpha_bits=%d\n",
|
||||
red_bits, green_bits, blue_bits, alpha_bits);
|
||||
|
||||
if (get_color_type() != color_type_rgb
|
||||
|| get_color_type() != color_type_rgb_alpha)
|
||||
{
|
||||
throw error("set_shift: expected RGB or RGBA color type");
|
||||
}
|
||||
color_info bits;
|
||||
bits.red = red_bits;
|
||||
bits.green = green_bits;
|
||||
bits.blue = blue_bits;
|
||||
bits.alpha = alpha_bits;
|
||||
png_set_shift(m_png, & bits);
|
||||
}
|
||||
|
||||
void set_shift(byte gray_bits, byte alpha_bits = 0) const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_shift: gray_bits=%d, alpha_bits=%d\n",
|
||||
gray_bits, alpha_bits);
|
||||
|
||||
if (get_color_type() != color_type_gray
|
||||
|| get_color_type() != color_type_gray_alpha)
|
||||
{
|
||||
throw error("set_shift: expected Gray or Gray+Alpha color type");
|
||||
}
|
||||
color_info bits;
|
||||
bits.gray = gray_bits;
|
||||
bits.alpha = alpha_bits;
|
||||
png_set_shift(m_png, & bits);
|
||||
}
|
||||
#endif // PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED
|
||||
|
||||
#if defined(PNG_READ_INTERLACING_SUPPORTED) \
|
||||
|| defined(PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
int set_interlace_handling() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_interlace_handling\n");
|
||||
return png_set_interlace_handling(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
|
||||
void set_invert_mono() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_invert_mono\n");
|
||||
png_set_invert_mono(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_16_TO_8_SUPPORTED)
|
||||
void set_strip_16() const
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_strip_16\n");
|
||||
png_set_strip_16(m_png);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
|
||||
void set_read_user_transform(png_user_transform_ptr transform_fn)
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_read_user_transform_fn\n");
|
||||
png_set_read_user_transform_fn(m_png, transform_fn);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) \
|
||||
|| defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
|
||||
void set_user_transform_info(void* info, int bit_depth, int channels)
|
||||
{
|
||||
TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d,"
|
||||
" channels=%d\n", bit_depth, channels);
|
||||
|
||||
png_set_user_transform_info(m_png, info, bit_depth, channels);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void* get_io_ptr() const
|
||||
{
|
||||
return png_get_io_ptr(m_png);
|
||||
}
|
||||
|
||||
void set_error(char const* message)
|
||||
{
|
||||
assert(message);
|
||||
m_error = message;
|
||||
}
|
||||
|
||||
void reset_error()
|
||||
{
|
||||
m_error.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
std::string const& get_error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
*/
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return !m_error.empty();
|
||||
}
|
||||
|
||||
void raise_error()
|
||||
{
|
||||
longjmp(png_jmpbuf(m_png), -1);
|
||||
}
|
||||
|
||||
static void raise_error(png_struct* png, char const* message)
|
||||
{
|
||||
io_base* io = static_cast< io_base* >(png_get_error_ptr(png));
|
||||
io->set_error(message);
|
||||
io->raise_error();
|
||||
}
|
||||
|
||||
png_struct* m_png;
|
||||
info m_info;
|
||||
end_info m_end_info;
|
||||
std::string m_error;
|
||||
};
|
||||
|
||||
} // namespace png
|
||||
|
||||
#endif // PNGPP_IO_BASE_HPP_INCLUDED
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
Libpng 1.6.34 - September 29, 2017
|
||||
|
||||
This is a public release of libpng, intended for use in production codes.
|
||||
|
||||
Files available for download:
|
||||
|
||||
Source files with LF line endings (for Unix/Linux) and with a
|
||||
"configure" script
|
||||
|
||||
libpng-1.6.34.tar.xz (LZMA-compressed, recommended)
|
||||
libpng-1.6.34.tar.gz
|
||||
|
||||
Source files with CRLF line endings (for Windows), without the
|
||||
"configure" script
|
||||
|
||||
lpng1634.7z (LZMA-compressed, recommended)
|
||||
lpng1634.zip
|
||||
|
||||
Other information:
|
||||
|
||||
libpng-1.6.34-README.txt
|
||||
libpng-1.6.34-LICENSE.txt
|
||||
libpng-1.6.34-*.asc (armored detached GPG signatures)
|
||||
|
||||
Changes since the last public release (1.6.33):
|
||||
Removed contrib/pngsuite/i*.png; some of these were incorrect and caused
|
||||
test failures.
|
||||
|
||||
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
|
||||
|
|
@ -1,937 +0,0 @@
|
|||
# CMakeLists.txt
|
||||
|
||||
# Copyright (C) 2007,2009-2017 Glenn Randers-Pehrson
|
||||
# Written by Christian Ehrlicher, 2007
|
||||
# Revised by Roger Lowman, 2009-2010
|
||||
# Revised by Clifford Yapp, 2011-2012
|
||||
# Revised by Roger Leigh, 2016
|
||||
# Revised by Andreas Franek, 2016
|
||||
|
||||
# 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.0.2)
|
||||
cmake_policy(VERSION 3.0.2)
|
||||
|
||||
# Set MacOSX @rpath usage globally.
|
||||
if (POLICY CMP0020)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
endif(POLICY CMP0020)
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif(POLICY CMP0042)
|
||||
# Use new variable expansion policy.
|
||||
if (POLICY CMP0053)
|
||||
cmake_policy(SET CMP0053 NEW)
|
||||
endif(POLICY CMP0053)
|
||||
if (POLICY CMP0054)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif(POLICY CMP0054)
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES "Release;Debug;MinSizeRel;RelWithDebInfo")
|
||||
|
||||
project(libpng ASM C)
|
||||
|
||||
set(PNGLIB_MAJOR 1)
|
||||
set(PNGLIB_MINOR 6)
|
||||
set(PNGLIB_RELEASE 34)
|
||||
set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
|
||||
set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
|
||||
|
||||
# needed packages
|
||||
|
||||
#Allow users to specify location of Zlib,
|
||||
# Useful if zlib is being built alongside this as a sub-project
|
||||
|
||||
set(PNG_BUILD_ZLIB ${CMAKE_CURRENT_SOURCE_DIR}/zlib)
|
||||
|
||||
if(NOT WIN32)
|
||||
find_library(M_LIBRARY
|
||||
NAMES m
|
||||
PATHS /usr/lib /usr/local/lib
|
||||
)
|
||||
if(NOT M_LIBRARY)
|
||||
message(STATUS "math lib 'libm' not found; floating point support disabled")
|
||||
endif()
|
||||
else()
|
||||
# not needed on windows
|
||||
set(M_LIBRARY "")
|
||||
endif()
|
||||
|
||||
# COMMAND LINE OPTIONS
|
||||
option(PNG_SHARED "Build shared lib" OFF)
|
||||
option(PNG_STATIC "Build static lib" ON)
|
||||
option(PNG_TESTS "Build libpng tests" OFF)
|
||||
|
||||
# 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(PNGARG "Disable ANSI-C prototypes" 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 "no")
|
||||
set(libpng_arm_sources
|
||||
arm/arm_init.c
|
||||
arm/filter_neon.S
|
||||
arm/filter_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 "no")
|
||||
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 "no")
|
||||
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 "no")
|
||||
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()
|
||||
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 "Invalid arguments. generate_out requires input.")
|
||||
endif()
|
||||
if (NOT _GC_OUTPUT)
|
||||
message(FATAL_ERROR "Invalid arguments. generate_out requires output.")
|
||||
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 "Invalid arguments. generate_out requires input.")
|
||||
endif()
|
||||
if (NOT _GO_OUTPUT)
|
||||
message(FATAL_ERROR "Invalid arguments. generate_out requires output.")
|
||||
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 "Invalid arguments. generate_source requires output.")
|
||||
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 dependend 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(MSVC)
|
||||
|
||||
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})
|
||||
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 "Invalid arguments. png_add_test requires name.")
|
||||
endif()
|
||||
if (NOT _PAT_COMMAND)
|
||||
message(FATAL_ERROR "Invalid arguments. png_add_test requires command.")
|
||||
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)
|
||||
if(CMAKE_MAJOR_VERSION GREATER 2) # have generator expressions
|
||||
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")
|
||||
else() # old 2.x add_test; limited and won't work well on Windows
|
||||
# Note LIBPNG is a dummy value as there are no generator expressions
|
||||
add_test("${_PAT_NAME}" "${CMAKE_COMMAND}"
|
||||
"-DLIBPNG=${CMAKE_CURRENT_BINARY_DIR}/libpng.so"
|
||||
"-DTEST_COMMAND=./${_PAT_COMMAND}"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
|
||||
endif()
|
||||
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 "Specify either a TARGET or a FILE for CREATE_SYMLINK to link to.")
|
||||
endif(NOT S_TARGET AND NOT S_FILE)
|
||||
|
||||
if(S_TARGET AND S_FILE)
|
||||
message(FATAL_ERROR "CREATE_SYMLINK called with both source file ${S_FILE} and build target ${S_TARGET} arguments - can only handle 1 type per call.")
|
||||
endif(S_TARGET AND S_FILE)
|
||||
|
||||
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 AND NOT MSYS)
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
else(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
endif(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
endif(S_FILE)
|
||||
|
||||
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 AND NOT MSYS)
|
||||
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(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
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(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
|
||||
endif(S_TARGET)
|
||||
|
||||
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(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
|
||||
# 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
|
||||
# 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_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)
|
||||
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(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
|
||||
# SET UP LINKS
|
||||
if(PNG_SHARED)
|
||||
set_target_properties(png PROPERTIES
|
||||
# VERSION 16.${PNGLIB_RELEASE}.1.6.34
|
||||
VERSION 16.${PNGLIB_RELEASE}.0
|
||||
SOVERSION 16
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
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 )
|
||||
install(TARGETS ${PNG_LIB_TARGETS}
|
||||
${PNG_EXPORT_RULE}
|
||||
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(CYGWIN OR MINGW)
|
||||
|
||||
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(NOT WIN32)
|
||||
endif(PNG_SHARED)
|
||||
|
||||
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(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
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(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
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(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW)
|
||||
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-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
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
|
||||
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.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are
|
||||
Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are
|
||||
derived from libpng-1.0.6, 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
|
||||
Mans Rullgard
|
||||
Cosmin Truta
|
||||
Gilles Vollant
|
||||
James Yu
|
||||
Mandar Sahastrabuddhe
|
||||
Google Inc.
|
||||
Vadim Barkov
|
||||
|
||||
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.
|
||||
|
||||
Some files in the "contrib" directory and some configure-generated
|
||||
files that are distributed with libpng have other copyright owners and
|
||||
are released under other open source licenses.
|
||||
|
||||
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
|
||||
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
|
||||
libpng-0.96, 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, are derived from libpng-0.88,
|
||||
and are 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
|
||||
|
||||
Some files in the "scripts" directory have other copyright owners
|
||||
but are released under this license.
|
||||
|
||||
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.
|
||||
|
||||
END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
|
||||
|
||||
TRADEMARK:
|
||||
|
||||
The name "libpng" has not been registered by the Copyright owner
|
||||
as a trademark in any jurisdiction. However, because libpng has
|
||||
been distributed and maintained world-wide, continually since 1995,
|
||||
the Copyright owner claims "common-law trademark protection" in any
|
||||
jurisdiction where common-law trademark is recognized.
|
||||
|
||||
OSI CERTIFICATION:
|
||||
|
||||
Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
|
||||
a certification mark of the Open Source Initiative. OSI has not addressed
|
||||
the additional disclaimers inserted at version 1.0.7.
|
||||
|
||||
EXPORT CONTROL:
|
||||
|
||||
The Copyright owner believes that the Export Control Classification
|
||||
Number (ECCN) for libpng is EAR99, which means not subject to export
|
||||
controls or International Traffic in Arms Regulations (ITAR) because
|
||||
it is open source, publicly available software, that does not contain
|
||||
any encryption software. See the EAR, paragraphs 734.3(b)(3) and
|
||||
734.7(b).
|
||||
|
||||
Glenn Randers-Pehrson
|
||||
glennrp at users.sourceforge.net
|
||||
September 29, 2017
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
|
||||
/* arm_init.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
* Last changed in libpng 1.6.22 [May 26, 2016]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
|
||||
* called.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
|
||||
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||
* run-time checks for CPU features if at all possible. In the case of the ARM
|
||||
* NEON instructions there is no processor-specific way of detecting the
|
||||
* presence of the required support, therefore run-time detection is extremely
|
||||
* OS specific.
|
||||
*
|
||||
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
|
||||
* a fragment of C source code which defines the png_have_neon function. There
|
||||
* are a number of implementations in contrib/arm-neon, but the only one that
|
||||
* has partial support is contrib/arm-neon/linux.c - a generic Linux
|
||||
* implementation which reads /proc/cpufino.
|
||||
*/
|
||||
#ifndef PNG_ARM_NEON_FILE
|
||||
# ifdef __linux__
|
||||
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_ARM_NEON_FILE
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
static int png_have_neon(png_structp png_ptr);
|
||||
#include PNG_ARM_NEON_FILE
|
||||
|
||||
#else /* PNG_ARM_NEON_FILE */
|
||||
# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
|
||||
#endif /* PNG_ARM_NEON_FILE */
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
|
||||
#endif
|
||||
|
||||
void
|
||||
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The switch statement is compiled in for ARM_NEON_API, the call to
|
||||
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
|
||||
* the check is only performed if the API has not set the NEON option on
|
||||
* or off explicitly. In this case the check controls what happens.
|
||||
*
|
||||
* If the CHECK is not compiled in and the option is UNSET the behavior prior
|
||||
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
|
||||
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
|
||||
* as documented in png.h
|
||||
*/
|
||||
png_debug(1, "in png_init_filter_functions_neon");
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
switch ((pp->options >> PNG_ARM_NEON) & 3)
|
||||
{
|
||||
case PNG_OPTION_UNSET:
|
||||
/* Allow the run-time check to execute if it has been enabled -
|
||||
* thus both API and CHECK can be turned on. If it isn't supported
|
||||
* this case will fall through to the 'default' below, which just
|
||||
* returns.
|
||||
*/
|
||||
#endif /* PNG_ARM_NEON_API_SUPPORTED */
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||
{
|
||||
static volatile sig_atomic_t no_neon = -1; /* not checked */
|
||||
|
||||
if (no_neon < 0)
|
||||
no_neon = !png_have_neon(pp);
|
||||
|
||||
if (no_neon)
|
||||
return;
|
||||
}
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
break;
|
||||
#endif
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
default: /* OFF or INVALID */
|
||||
return;
|
||||
|
||||
case PNG_OPTION_ON:
|
||||
/* Option turned on */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IMPORTANT: any new external functions used here must be declared using
|
||||
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||
* 'prefix' option to configure works:
|
||||
*
|
||||
* ./configure --with-libpng-prefix=foobar_
|
||||
*
|
||||
* Verify you have got this right by running the above command, doing a build
|
||||
* and examining pngprefix.h; it must contain a #define for every external
|
||||
* function you add. (Notice that this happens automatically for the
|
||||
* initialization function.)
|
||||
*/
|
||||
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
|
||||
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth3_neon;
|
||||
}
|
||||
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth4_neon;
|
||||
}
|
||||
}
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
|
||||
/* filter_neon.S - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
* Last changed in libpng 1.6.31 [July 27, 2017]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* This is required to get the symbol renames, which are #defines, and the
|
||||
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
|
||||
*/
|
||||
#define PNG_VERSION_INFO_ONLY
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
|
||||
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
|
||||
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
|
||||
* for the logic which sets PNG_USE_ARM_NEON_ASM:
|
||||
*/
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
#ifdef __ELF__
|
||||
# define ELF
|
||||
#else
|
||||
# define ELF @
|
||||
#endif
|
||||
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
.macro func name, export=0
|
||||
.macro endfunc
|
||||
ELF .size \name, . - \name
|
||||
.endfunc
|
||||
.purgem endfunc
|
||||
.endm
|
||||
.text
|
||||
|
||||
/* Explicitly specifying alignment here because some versions of
|
||||
* GAS don't align code correctly. This is harmless in correctly
|
||||
* written versions of GAS.
|
||||
*/
|
||||
.align 2
|
||||
|
||||
.if \export
|
||||
.global \name
|
||||
.endif
|
||||
ELF .type \name, STT_FUNC
|
||||
.func \name
|
||||
\name:
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_sub4_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vadd.u8 d0, d3, d4
|
||||
vadd.u8 d1, d0, d5
|
||||
vadd.u8 d2, d1, d6
|
||||
vadd.u8 d3, d2, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_sub3_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r2, #3
|
||||
mov r12, #12
|
||||
vld1.8 {q11}, [r0], r12
|
||||
1:
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d3, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d0, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], r12
|
||||
vst1.32 {d0[0]}, [r1,:32], r2
|
||||
vadd.u8 d2, d1, d6
|
||||
vst1.32 {d1[0]}, [r1], r2
|
||||
vadd.u8 d3, d2, d7
|
||||
vst1.32 {d2[0]}, [r1], r2
|
||||
vst1.32 {d3[0]}, [r1], r2
|
||||
subs r3, r3, #12
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_up_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
1:
|
||||
vld1.8 {q0}, [r1,:128]
|
||||
vld1.8 {q1}, [r2,:128]!
|
||||
vadd.u8 q0, q0, q1
|
||||
vst1.8 {q0}, [r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
vhadd.u8 d0, d3, d16
|
||||
vadd.u8 d0, d0, d4
|
||||
vhadd.u8 d1, d0, d17
|
||||
vadd.u8 d1, d1, d5
|
||||
vhadd.u8 d2, d1, d18
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
vext.8 d5, d22, d23, #3
|
||||
vhadd.u8 d0, d3, d20
|
||||
vext.8 d17, d20, d21, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vhadd.u8 d1, d0, d17
|
||||
vext.8 d18, d20, d21, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vhadd.u8 d2, d1, d18
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vext.8 d19, d21, d21, #1
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
|
||||
.macro paeth rx, ra, rb, rc
|
||||
vaddl.u8 q12, \ra, \rb @ a + b
|
||||
vaddl.u8 q15, \rc, \rc @ 2*c
|
||||
vabdl.u8 q13, \rb, \rc @ pa
|
||||
vabdl.u8 q14, \ra, \rc @ pb
|
||||
vabd.u16 q15, q12, q15 @ pc
|
||||
vcle.u16 q12, q13, q14 @ pa <= pb
|
||||
vcle.u16 q13, q13, q15 @ pa <= pc
|
||||
vcle.u16 q14, q14, q15 @ pb <= pc
|
||||
vand q12, q12, q13 @ pa <= pb && pa <= pc
|
||||
vmovn.u16 d28, q14
|
||||
vmovn.u16 \rx, q12
|
||||
vbsl d28, \rb, \rc
|
||||
vbsl \rx, \ra, d28
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_paeth4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d20, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
paeth d0, d3, d16, d20
|
||||
vadd.u8 d0, d0, d4
|
||||
paeth d1, d0, d17, d16
|
||||
vadd.u8 d1, d1, d5
|
||||
paeth d2, d1, d18, d17
|
||||
vadd.u8 d2, d2, d6
|
||||
paeth d3, d2, d19, d18
|
||||
vmov d20, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_paeth3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d4, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
paeth d0, d3, d20, d4
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d17, d20, d21, #3
|
||||
paeth d1, d0, d17, d20
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d18, d20, d21, #6
|
||||
paeth d2, d1, d18, d17
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vadd.u8 d2, d2, d6
|
||||
vext.8 d19, d21, d21, #1
|
||||
paeth d3, d2, d19, d18
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vmov d4, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,387 +0,0 @@
|
|||
|
||||
/* filter_neon_intrinsics.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||
* Written by James Yu <james.yu at linaro.org>, October 2013.
|
||||
* Based on filter_neon.S, written by Mans Rullgard, 2011.
|
||||
*
|
||||
* Last changed in libpng 1.6.22 [May 26, 2016]
|
||||
*
|
||||
* 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_READ_SUPPORTED
|
||||
|
||||
/* This code requires -mfpu=neon on the command line: */
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
||||
* however this code will only work with appropriate alignment. arm/arm_init.c
|
||||
* checks for this (and will not compile unless it is done). This code uses
|
||||
* variants of png_aligncast to avoid compiler warnings.
|
||||
*/
|
||||
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
||||
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
||||
|
||||
/* The following relies on a variable 'temp_pointer' being declared with type
|
||||
* 'type'. This is written this way just to hide the GCC strict aliasing
|
||||
* warning; note that the code is safe because there never is an alias between
|
||||
* the input and output pointers.
|
||||
*/
|
||||
#define png_ldr(type,pointer)\
|
||||
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
void
|
||||
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_up_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint8x16_t qrp, qpp;
|
||||
|
||||
qrp = vld1q_u8(rp);
|
||||
qpp = vld1q_u8(pp);
|
||||
qrp = vaddq_u8(qrp, qpp);
|
||||
vst1q_u8(rp, qrp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp = vld1q_u8(rp);
|
||||
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
uint8x8x2_t vrp = *vrpt;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub3_neon");
|
||||
|
||||
for (; rp < rp_stop;)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
|
||||
PNG_UNUSED(prev_row)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
uint8x8x4_t vrp = *vrpt;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
|
||||
PNG_UNUSED(prev_row)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg3_neon");
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8x8_t
|
||||
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
|
||||
{
|
||||
uint8x8_t d, e;
|
||||
uint16x8_t p1, pa, pb, pc;
|
||||
|
||||
p1 = vaddl_u8(a, b); /* a + b */
|
||||
pc = vaddl_u8(c, c); /* c * 2 */
|
||||
pa = vabdl_u8(b, c); /* pa */
|
||||
pb = vabdl_u8(a, c); /* pb */
|
||||
pc = vabdq_u16(p1, pc); /* pc */
|
||||
|
||||
p1 = vcleq_u16(pa, pb); /* pa <= pb */
|
||||
pa = vcleq_u16(pa, pc); /* pa <= pc */
|
||||
pb = vcleq_u16(pb, pc); /* pb <= pc */
|
||||
|
||||
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
|
||||
|
||||
d = vmovn_u16(pb);
|
||||
e = vmovn_u16(p1);
|
||||
|
||||
d = vbsl_u8(d, b, c);
|
||||
e = vbsl_u8(e, a, d);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth3_neon");
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vlast = vtmp2;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vlast = vpp.val[3];
|
||||
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,406 +0,0 @@
|
|||
|
||||
/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
|
||||
*
|
||||
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
|
||||
* Written by Mike Klein and Matt Sarett
|
||||
* Derived from arm/filter_neon_intrinsics.c
|
||||
*
|
||||
* Last changed in libpng 1.6.31 [July 27, 2017]
|
||||
*
|
||||
* 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_READ_SUPPORTED
|
||||
|
||||
#if PNG_INTEL_SSE_IMPLEMENTATION > 0
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
|
||||
* They're positioned like this:
|
||||
* prev: c b
|
||||
* row: a d
|
||||
* The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
|
||||
* whichever of a, b, or c is closest to p=a+b-c.
|
||||
*/
|
||||
|
||||
static __m128i load4(const void* p) {
|
||||
return _mm_cvtsi32_si128(*(const int*)p);
|
||||
}
|
||||
|
||||
static void store4(void* p, __m128i v) {
|
||||
*(int*)p = _mm_cvtsi128_si32(v);
|
||||
}
|
||||
|
||||
static __m128i load3(const void* p) {
|
||||
/* We'll load 2 bytes, then 1 byte,
|
||||
* then mask them together, and finally load into SSE.
|
||||
*/
|
||||
const png_uint_16* p01 = (png_const_uint_16p)p;
|
||||
const png_byte* p2 = (const png_byte*)(p01+1);
|
||||
|
||||
png_uint_32 v012 = (png_uint_32)(*p01)
|
||||
| (png_uint_32)(*p2) << 16;
|
||||
return load4(&v012);
|
||||
}
|
||||
|
||||
static void store3(void* p, __m128i v) {
|
||||
/* We'll pull from SSE as a 32-bit int, then write
|
||||
* its bottom two bytes, then its third byte.
|
||||
*/
|
||||
png_uint_32 v012;
|
||||
png_uint_16* p01;
|
||||
png_byte* p2;
|
||||
|
||||
store4(&v012, v);
|
||||
|
||||
p01 = (png_uint_16p)p;
|
||||
p2 = (png_byte*)(p01+1);
|
||||
*p01 = (png_uint_16)v012;
|
||||
*p2 = (png_byte)(v012 >> 16);
|
||||
}
|
||||
|
||||
void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* The Sub filter predicts each pixel as the previous pixel, a.
|
||||
* There is no pixel to the left of the first pixel. It's encoded directly.
|
||||
* That works with our main loop if we just say that left pixel was zero.
|
||||
*/
|
||||
png_size_t rb;
|
||||
|
||||
__m128i a, d = _mm_setzero_si128();
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub3_sse2");
|
||||
|
||||
rb = row_info->rowbytes;
|
||||
while (rb >= 4) {
|
||||
a = d; d = load4(row);
|
||||
d = _mm_add_epi8(d, a);
|
||||
store3(row, d);
|
||||
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
if (rb > 0) {
|
||||
a = d; d = load3(row);
|
||||
d = _mm_add_epi8(d, a);
|
||||
store3(row, d);
|
||||
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
PNG_UNUSED(prev)
|
||||
}
|
||||
|
||||
void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* The Sub filter predicts each pixel as the previous pixel, a.
|
||||
* There is no pixel to the left of the first pixel. It's encoded directly.
|
||||
* That works with our main loop if we just say that left pixel was zero.
|
||||
*/
|
||||
png_size_t rb;
|
||||
|
||||
__m128i a, d = _mm_setzero_si128();
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub4_sse2");
|
||||
|
||||
rb = row_info->rowbytes+4;
|
||||
while (rb > 4) {
|
||||
a = d; d = load4(row);
|
||||
d = _mm_add_epi8(d, a);
|
||||
store4(row, d);
|
||||
|
||||
row += 4;
|
||||
rb -= 4;
|
||||
}
|
||||
PNG_UNUSED(prev)
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* The Avg filter predicts each pixel as the (truncated) average of a and b.
|
||||
* There's no pixel to the left of the first pixel. Luckily, it's
|
||||
* predicted to be half of the pixel above it. So again, this works
|
||||
* perfectly with our loop if we make sure a starts at zero.
|
||||
*/
|
||||
|
||||
png_size_t rb;
|
||||
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
|
||||
__m128i b;
|
||||
__m128i a, d = zero;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg3_sse2");
|
||||
rb = row_info->rowbytes;
|
||||
while (rb >= 4) {
|
||||
__m128i avg;
|
||||
b = load4(prev);
|
||||
a = d; d = load4(row );
|
||||
|
||||
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
|
||||
avg = _mm_avg_epu8(a,b);
|
||||
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
|
||||
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
|
||||
_mm_set1_epi8(1)));
|
||||
d = _mm_add_epi8(d, avg);
|
||||
store3(row, d);
|
||||
|
||||
prev += 3;
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
if (rb > 0) {
|
||||
__m128i avg;
|
||||
b = load3(prev);
|
||||
a = d; d = load3(row );
|
||||
|
||||
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
|
||||
avg = _mm_avg_epu8(a,b);
|
||||
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
|
||||
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
|
||||
_mm_set1_epi8(1)));
|
||||
|
||||
d = _mm_add_epi8(d, avg);
|
||||
store3(row, d);
|
||||
|
||||
prev += 3;
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* The Avg filter predicts each pixel as the (truncated) average of a and b.
|
||||
* There's no pixel to the left of the first pixel. Luckily, it's
|
||||
* predicted to be half of the pixel above it. So again, this works
|
||||
* perfectly with our loop if we make sure a starts at zero.
|
||||
*/
|
||||
png_size_t rb;
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i b;
|
||||
__m128i a, d = zero;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg4_sse2");
|
||||
|
||||
rb = row_info->rowbytes+4;
|
||||
while (rb > 4) {
|
||||
__m128i avg;
|
||||
b = load4(prev);
|
||||
a = d; d = load4(row );
|
||||
|
||||
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
|
||||
avg = _mm_avg_epu8(a,b);
|
||||
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
|
||||
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
|
||||
_mm_set1_epi8(1)));
|
||||
|
||||
d = _mm_add_epi8(d, avg);
|
||||
store4(row, d);
|
||||
|
||||
prev += 4;
|
||||
row += 4;
|
||||
rb -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns |x| for 16-bit lanes. */
|
||||
static __m128i abs_i16(__m128i x) {
|
||||
#if PNG_INTEL_SSE_IMPLEMENTATION >= 2
|
||||
return _mm_abs_epi16(x);
|
||||
#else
|
||||
/* Read this all as, return x<0 ? -x : x.
|
||||
* To negate two's complement, you flip all the bits then add 1.
|
||||
*/
|
||||
__m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128());
|
||||
|
||||
/* Flip negative lanes. */
|
||||
x = _mm_xor_si128(x, is_negative);
|
||||
|
||||
/* +1 to negative lanes, else +0. */
|
||||
x = _mm_sub_epi16(x, is_negative);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Bytewise c ? t : e. */
|
||||
static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
|
||||
#if PNG_INTEL_SSE_IMPLEMENTATION >= 3
|
||||
return _mm_blendv_epi8(e,t,c);
|
||||
#else
|
||||
return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
|
||||
#endif
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* Paeth tries to predict pixel d using the pixel to the left of it, a,
|
||||
* and two pixels from the previous row, b and c:
|
||||
* prev: c b
|
||||
* row: a d
|
||||
* The Paeth function predicts d to be whichever of a, b, or c is nearest to
|
||||
* p=a+b-c.
|
||||
*
|
||||
* The first pixel has no left context, and so uses an Up filter, p = b.
|
||||
* This works naturally with our main loop's p = a+b-c if we force a and c
|
||||
* to zero.
|
||||
* Here we zero b and d, which become c and a respectively at the start of
|
||||
* the loop.
|
||||
*/
|
||||
png_size_t rb;
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i c, b = zero,
|
||||
a, d = zero;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth3_sse2");
|
||||
|
||||
rb = row_info->rowbytes;
|
||||
while (rb >= 4) {
|
||||
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
|
||||
* intermediates.
|
||||
*/
|
||||
__m128i pa,pb,pc,smallest,nearest;
|
||||
c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
|
||||
a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
|
||||
|
||||
/* (p-a) == (a+b-c - a) == (b-c) */
|
||||
|
||||
pa = _mm_sub_epi16(b,c);
|
||||
|
||||
/* (p-b) == (a+b-c - b) == (a-c) */
|
||||
pb = _mm_sub_epi16(a,c);
|
||||
|
||||
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
|
||||
pc = _mm_add_epi16(pa,pb);
|
||||
|
||||
pa = abs_i16(pa); /* |p-a| */
|
||||
pb = abs_i16(pb); /* |p-b| */
|
||||
pc = abs_i16(pc); /* |p-c| */
|
||||
|
||||
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
|
||||
|
||||
/* Paeth breaks ties favoring a over b over c. */
|
||||
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
|
||||
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
|
||||
c));
|
||||
|
||||
/* Note `_epi8`: we need addition to wrap modulo 255. */
|
||||
d = _mm_add_epi8(d, nearest);
|
||||
store3(row, _mm_packus_epi16(d,d));
|
||||
|
||||
prev += 3;
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
if (rb > 0) {
|
||||
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
|
||||
* intermediates.
|
||||
*/
|
||||
__m128i pa,pb,pc,smallest,nearest;
|
||||
c = b; b = _mm_unpacklo_epi8(load3(prev), zero);
|
||||
a = d; d = _mm_unpacklo_epi8(load3(row ), zero);
|
||||
|
||||
/* (p-a) == (a+b-c - a) == (b-c) */
|
||||
pa = _mm_sub_epi16(b,c);
|
||||
|
||||
/* (p-b) == (a+b-c - b) == (a-c) */
|
||||
pb = _mm_sub_epi16(a,c);
|
||||
|
||||
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
|
||||
pc = _mm_add_epi16(pa,pb);
|
||||
|
||||
pa = abs_i16(pa); /* |p-a| */
|
||||
pb = abs_i16(pb); /* |p-b| */
|
||||
pc = abs_i16(pc); /* |p-c| */
|
||||
|
||||
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
|
||||
|
||||
/* Paeth breaks ties favoring a over b over c. */
|
||||
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
|
||||
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
|
||||
c));
|
||||
|
||||
/* Note `_epi8`: we need addition to wrap modulo 255. */
|
||||
d = _mm_add_epi8(d, nearest);
|
||||
store3(row, _mm_packus_epi16(d,d));
|
||||
|
||||
prev += 3;
|
||||
row += 3;
|
||||
rb -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev)
|
||||
{
|
||||
/* Paeth tries to predict pixel d using the pixel to the left of it, a,
|
||||
* and two pixels from the previous row, b and c:
|
||||
* prev: c b
|
||||
* row: a d
|
||||
* The Paeth function predicts d to be whichever of a, b, or c is nearest to
|
||||
* p=a+b-c.
|
||||
*
|
||||
* The first pixel has no left context, and so uses an Up filter, p = b.
|
||||
* This works naturally with our main loop's p = a+b-c if we force a and c
|
||||
* to zero.
|
||||
* Here we zero b and d, which become c and a respectively at the start of
|
||||
* the loop.
|
||||
*/
|
||||
png_size_t rb;
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i pa,pb,pc,smallest,nearest;
|
||||
__m128i c, b = zero,
|
||||
a, d = zero;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth4_sse2");
|
||||
|
||||
rb = row_info->rowbytes+4;
|
||||
while (rb > 4) {
|
||||
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
|
||||
* intermediates.
|
||||
*/
|
||||
c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
|
||||
a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
|
||||
|
||||
/* (p-a) == (a+b-c - a) == (b-c) */
|
||||
pa = _mm_sub_epi16(b,c);
|
||||
|
||||
/* (p-b) == (a+b-c - b) == (a-c) */
|
||||
pb = _mm_sub_epi16(a,c);
|
||||
|
||||
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
|
||||
pc = _mm_add_epi16(pa,pb);
|
||||
|
||||
pa = abs_i16(pa); /* |p-a| */
|
||||
pb = abs_i16(pb); /* |p-b| */
|
||||
pc = abs_i16(pc); /* |p-c| */
|
||||
|
||||
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
|
||||
|
||||
/* Paeth breaks ties favoring a over b over c. */
|
||||
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
|
||||
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
|
||||
c));
|
||||
|
||||
/* Note `_epi8`: we need addition to wrap modulo 255. */
|
||||
d = _mm_add_epi8(d, nearest);
|
||||
store4(row, _mm_packus_epi16(d,d));
|
||||
|
||||
prev += 4;
|
||||
row += 4;
|
||||
rb -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
|
||||
/* intel_init.c - SSE2 optimized filter functions
|
||||
*
|
||||
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
|
||||
* Written by Mike Klein and Matt Sarett, Google, Inc.
|
||||
* Derived from arm/arm_init.c
|
||||
*
|
||||
* Last changed in libpng 1.6.29 [March 16, 2017]
|
||||
*
|
||||
* 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_READ_SUPPORTED
|
||||
#if PNG_INTEL_SSE_IMPLEMENTATION > 0
|
||||
|
||||
void
|
||||
png_init_filter_functions_sse2(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The techniques used to implement each of these filters in SSE operate on
|
||||
* one pixel at a time.
|
||||
* So they generally speed up 3bpp images about 3x, 4bpp images about 4x.
|
||||
* They can scale up to 6 and 8 bpp images and down to 2 bpp images,
|
||||
* but they'd not likely have any benefit for 1bpp images.
|
||||
* Most of these can be implemented using only MMX and 64-bit registers,
|
||||
* but they end up a bit slower than using the equally-ubiquitous SSE2.
|
||||
*/
|
||||
png_debug(1, "in png_init_filter_functions_sse2");
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth3_sse2;
|
||||
}
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth4_sse2;
|
||||
}
|
||||
|
||||
/* No need optimize PNG_FILTER_VALUE_UP. The compiler should
|
||||
* autovectorize.
|
||||
*/
|
||||
}
|
||||
|
||||
#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
# libpng-config
|
||||
# provides configuration info for libpng.
|
||||
|
||||
# Copyright (C) 2002, 2004, 2006, 2007 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
|
||||
|
||||
# Modeled after libxml-config.
|
||||
|
||||
version="@PNGLIB_VERSION@"
|
||||
prefix="@prefix@"
|
||||
exec_prefix="@exec_prefix@"
|
||||
libdir="@libdir@"
|
||||
includedir="@includedir@/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@"
|
||||
libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@"
|
||||
all_libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ @LIBS@"
|
||||
I_opts="-I${includedir}"
|
||||
L_opts="-L${libdir}"
|
||||
R_opts=""
|
||||
cppflags=""
|
||||
ccopts=""
|
||||
ldopts=""
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTION] ...
|
||||
|
||||
Known values for OPTION are:
|
||||
|
||||
--prefix print libpng prefix
|
||||
--libdir print path to directory containing library
|
||||
--libs print library linking information
|
||||
--ccopts print compiler options
|
||||
--cppflags print pre-processor flags
|
||||
--cflags print preprocessor flags, I_opts, and compiler options
|
||||
--I_opts print "-I" include options
|
||||
--L_opts print linker "-L" flags for dynamic linking
|
||||
--R_opts print dynamic linker "-R" or "-rpath" flags
|
||||
--ldopts print linker options
|
||||
--ldflags print linker flags (ldopts, L_opts, R_opts, and libs)
|
||||
--static revise subsequent outputs for static linking
|
||||
--help print this help and exit
|
||||
--version print version information
|
||||
EOF
|
||||
|
||||
exit $1
|
||||
}
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
|
||||
--prefix)
|
||||
echo ${prefix}
|
||||
;;
|
||||
|
||||
--version)
|
||||
echo ${version}
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--help)
|
||||
usage 0
|
||||
;;
|
||||
|
||||
--ccopts)
|
||||
echo ${ccopts}
|
||||
;;
|
||||
|
||||
--cppflags)
|
||||
echo ${cppflags}
|
||||
;;
|
||||
|
||||
--cflags)
|
||||
echo ${I_opts} ${cppflags} ${ccopts}
|
||||
;;
|
||||
|
||||
--libdir)
|
||||
echo ${libdir}
|
||||
;;
|
||||
|
||||
--libs)
|
||||
echo ${libs}
|
||||
;;
|
||||
|
||||
--I_opts)
|
||||
echo ${I_opts}
|
||||
;;
|
||||
|
||||
--L_opts)
|
||||
echo ${L_opts}
|
||||
;;
|
||||
|
||||
--R_opts)
|
||||
echo ${R_opts}
|
||||
;;
|
||||
|
||||
--ldopts)
|
||||
echo ${ldopts}
|
||||
;;
|
||||
|
||||
--ldflags)
|
||||
echo ${ldopts} ${L_opts} ${R_opts} ${libs}
|
||||
;;
|
||||
|
||||
--static)
|
||||
R_opts=""
|
||||
libs=${all_libs}
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
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@
|
||||
Requires: zlib
|
||||
Libs: -L${libdir} -lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
|
||||
Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
|
@ -1,807 +0,0 @@
|
|||
|
||||
/* filter_msa_intrinsics.c - MSA optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Randers-Pehrson
|
||||
* Written by Mandar Sahastrabuddhe, August 2016.
|
||||
* Last changed in libpng 1.6.25 [September 1, 2016]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* This code requires -mfpu=msa on the command line: */
|
||||
#if PNG_MIPS_MSA_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||
|
||||
#include <msa.h>
|
||||
|
||||
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
||||
* however this code will only work with appropriate alignment. mips/mips_init.c
|
||||
* checks for this (and will not compile unless it is done). This code uses
|
||||
* variants of png_aligncast to avoid compiler warnings.
|
||||
*/
|
||||
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
||||
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
||||
|
||||
/* The following relies on a variable 'temp_pointer' being declared with type
|
||||
* 'type'. This is written this way just to hide the GCC strict aliasing
|
||||
* warning; note that the code is safe because there never is an alias between
|
||||
* the input and output pointers.
|
||||
*/
|
||||
#define png_ldr(type,pointer)\
|
||||
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
||||
|
||||
#if PNG_MIPS_MSA_OPT > 0
|
||||
|
||||
#ifdef CLANG_BUILD
|
||||
#define MSA_SRLI_B(a, b) __msa_srli_b((v16i8) a, b)
|
||||
|
||||
#define LW(psrc) \
|
||||
( { \
|
||||
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
|
||||
uint32_t val_m; \
|
||||
\
|
||||
asm volatile ( \
|
||||
"lw %[val_m], %[psrc_lw_m] \n\t" \
|
||||
\
|
||||
: [val_m] "=r" (val_m) \
|
||||
: [psrc_lw_m] "m" (*psrc_lw_m) \
|
||||
); \
|
||||
\
|
||||
val_m; \
|
||||
} )
|
||||
|
||||
#define SH(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
|
||||
uint16_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sh %[val_m], %[pdst_sh_m] \n\t" \
|
||||
\
|
||||
: [pdst_sh_m] "=m" (*pdst_sh_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SW(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
|
||||
uint32_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sw %[val_m], %[pdst_sw_m] \n\t" \
|
||||
\
|
||||
: [pdst_sw_m] "=m" (*pdst_sw_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#if (__mips == 64)
|
||||
#define SD(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
|
||||
uint64_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sd %[val_m], %[pdst_sd_m] \n\t" \
|
||||
\
|
||||
: [pdst_sd_m] "=m" (*pdst_sd_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define SD(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
|
||||
uint32_t val0_m, val1_m; \
|
||||
\
|
||||
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
|
||||
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
|
||||
\
|
||||
SW(val0_m, pdst_sd_m); \
|
||||
SW(val1_m, pdst_sd_m + 4); \
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define MSA_SRLI_B(a, b) (a >> b)
|
||||
|
||||
#if (__mips_isa_rev >= 6)
|
||||
#define LW(psrc) \
|
||||
( { \
|
||||
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
|
||||
uint32_t val_m; \
|
||||
\
|
||||
asm volatile ( \
|
||||
"lw %[val_m], %[psrc_lw_m] \n\t" \
|
||||
\
|
||||
: [val_m] "=r" (val_m) \
|
||||
: [psrc_lw_m] "m" (*psrc_lw_m) \
|
||||
); \
|
||||
\
|
||||
val_m; \
|
||||
} )
|
||||
|
||||
#define SH(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
|
||||
uint16_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sh %[val_m], %[pdst_sh_m] \n\t" \
|
||||
\
|
||||
: [pdst_sh_m] "=m" (*pdst_sh_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SW(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
|
||||
uint32_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sw %[val_m], %[pdst_sw_m] \n\t" \
|
||||
\
|
||||
: [pdst_sw_m] "=m" (*pdst_sw_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#if (__mips == 64)
|
||||
#define SD(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
|
||||
uint64_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"sd %[val_m], %[pdst_sd_m] \n\t" \
|
||||
\
|
||||
: [pdst_sd_m] "=m" (*pdst_sd_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define SD(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
|
||||
uint32_t val0_m, val1_m; \
|
||||
\
|
||||
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
|
||||
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
|
||||
\
|
||||
SW(val0_m, pdst_sd_m); \
|
||||
SW(val1_m, pdst_sd_m + 4); \
|
||||
}
|
||||
#endif
|
||||
#else // !(__mips_isa_rev >= 6)
|
||||
#define LW(psrc) \
|
||||
( { \
|
||||
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
|
||||
uint32_t val_m; \
|
||||
\
|
||||
asm volatile ( \
|
||||
"ulw %[val_m], %[psrc_lw_m] \n\t" \
|
||||
\
|
||||
: [val_m] "=r" (val_m) \
|
||||
: [psrc_lw_m] "m" (*psrc_lw_m) \
|
||||
); \
|
||||
\
|
||||
val_m; \
|
||||
} )
|
||||
|
||||
#define SH(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
|
||||
uint16_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"ush %[val_m], %[pdst_sh_m] \n\t" \
|
||||
\
|
||||
: [pdst_sh_m] "=m" (*pdst_sh_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SW(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
|
||||
uint32_t val_m = (val); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"usw %[val_m], %[pdst_sw_m] \n\t" \
|
||||
\
|
||||
: [pdst_sw_m] "=m" (*pdst_sw_m) \
|
||||
: [val_m] "r" (val_m) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SD(val, pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
|
||||
uint32_t val0_m, val1_m; \
|
||||
\
|
||||
val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \
|
||||
val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \
|
||||
\
|
||||
SW(val0_m, pdst_sd_m); \
|
||||
SW(val1_m, pdst_sd_m + 4); \
|
||||
}
|
||||
|
||||
#define SW_ZERO(pdst) \
|
||||
{ \
|
||||
uint8_t *pdst_m = (uint8_t *) (pdst); \
|
||||
\
|
||||
asm volatile ( \
|
||||
"usw $0, %[pdst_m] \n\t" \
|
||||
\
|
||||
: [pdst_m] "=m" (*pdst_m) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
#endif // (__mips_isa_rev >= 6)
|
||||
#endif
|
||||
|
||||
#define LD_B(RTYPE, psrc) *((RTYPE *) (psrc))
|
||||
#define LD_UB(...) LD_B(v16u8, __VA_ARGS__)
|
||||
#define LD_B2(RTYPE, psrc, stride, out0, out1) \
|
||||
{ \
|
||||
out0 = LD_B(RTYPE, (psrc)); \
|
||||
out1 = LD_B(RTYPE, (psrc) + stride); \
|
||||
}
|
||||
#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
|
||||
#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) \
|
||||
{ \
|
||||
LD_B2(RTYPE, (psrc), stride, out0, out1); \
|
||||
LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3); \
|
||||
}
|
||||
#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
|
||||
|
||||
#define ST_B(RTYPE, in, pdst) *((RTYPE *) (pdst)) = (in)
|
||||
#define ST_UB(...) ST_B(v16u8, __VA_ARGS__)
|
||||
#define ST_B2(RTYPE, in0, in1, pdst, stride) \
|
||||
{ \
|
||||
ST_B(RTYPE, in0, (pdst)); \
|
||||
ST_B(RTYPE, in1, (pdst) + stride); \
|
||||
}
|
||||
#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__)
|
||||
#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) \
|
||||
{ \
|
||||
ST_B2(RTYPE, in0, in1, (pdst), stride); \
|
||||
ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \
|
||||
}
|
||||
#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__)
|
||||
|
||||
#define ADD2(in0, in1, in2, in3, out0, out1) \
|
||||
{ \
|
||||
out0 = in0 + in1; \
|
||||
out1 = in2 + in3; \
|
||||
}
|
||||
#define ADD3(in0, in1, in2, in3, in4, in5, \
|
||||
out0, out1, out2) \
|
||||
{ \
|
||||
ADD2(in0, in1, in2, in3, out0, out1); \
|
||||
out2 = in4 + in5; \
|
||||
}
|
||||
#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \
|
||||
out0, out1, out2, out3) \
|
||||
{ \
|
||||
ADD2(in0, in1, in2, in3, out0, out1); \
|
||||
ADD2(in4, in5, in6, in7, out2, out3); \
|
||||
}
|
||||
|
||||
#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) \
|
||||
{ \
|
||||
out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1); \
|
||||
out1 = (RTYPE) __msa_ilvr_b((v16i8) in2, (v16i8) in3); \
|
||||
}
|
||||
#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__)
|
||||
|
||||
#define HSUB_UB2(RTYPE, in0, in1, out0, out1) \
|
||||
{ \
|
||||
out0 = (RTYPE) __msa_hsub_u_h((v16u8) in0, (v16u8) in0); \
|
||||
out1 = (RTYPE) __msa_hsub_u_h((v16u8) in1, (v16u8) in1); \
|
||||
}
|
||||
#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__)
|
||||
|
||||
#define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val) \
|
||||
{ \
|
||||
v16i8 zero_m = { 0 }; \
|
||||
out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val); \
|
||||
out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val); \
|
||||
}
|
||||
#define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__)
|
||||
|
||||
#define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2, slide_val) \
|
||||
{ \
|
||||
v16i8 zero_m = { 0 }; \
|
||||
SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val); \
|
||||
out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val); \
|
||||
}
|
||||
#define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__)
|
||||
|
||||
#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) \
|
||||
{ \
|
||||
out0 = (RTYPE) __msa_ilvev_w((v4i32) in1, (v4i32) in0); \
|
||||
out1 = (RTYPE) __msa_ilvev_w((v4i32) in3, (v4i32) in2); \
|
||||
}
|
||||
#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__)
|
||||
|
||||
#define ADD_ABS_H3(RTYPE, in0, in1, in2, out0, out1, out2) \
|
||||
{ \
|
||||
RTYPE zero = {0}; \
|
||||
\
|
||||
out0 = __msa_add_a_h((v8i16) zero, in0); \
|
||||
out1 = __msa_add_a_h((v8i16) zero, in1); \
|
||||
out2 = __msa_add_a_h((v8i16) zero, in2); \
|
||||
}
|
||||
#define ADD_ABS_H3_SH(...) ADD_ABS_H3(v8i16, __VA_ARGS__)
|
||||
|
||||
#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) \
|
||||
{ \
|
||||
out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0); \
|
||||
out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2); \
|
||||
}
|
||||
#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
|
||||
|
||||
#define CMP_AND_SELECT(inp0, inp1, inp2, inp3, inp4, inp5, out0) \
|
||||
{ \
|
||||
v8i16 _sel_h0, _sel_h1; \
|
||||
v16u8 _sel_b0, _sel_b1; \
|
||||
_sel_h0 = (v8i16) __msa_clt_u_h((v8u16) inp1, (v8u16) inp0); \
|
||||
_sel_b0 = (v16u8) __msa_pckev_b((v16i8) _sel_h0, (v16i8) _sel_h0); \
|
||||
inp0 = (v8i16) __msa_bmnz_v((v16u8) inp0, (v16u8) inp1, (v16u8) _sel_h0); \
|
||||
inp4 = (v16u8) __msa_bmnz_v(inp3, inp4, _sel_b0); \
|
||||
_sel_h1 = (v8i16) __msa_clt_u_h((v8u16) inp2, (v8u16) inp0); \
|
||||
_sel_b1 = (v16u8) __msa_pckev_b((v16i8) _sel_h1, (v16i8) _sel_h1); \
|
||||
inp4 = (v16u8) __msa_bmnz_v(inp4, inp5, _sel_b1); \
|
||||
out0 += inp4; \
|
||||
}
|
||||
|
||||
void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_size_t i, cnt, cnt16, cnt32;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
|
||||
|
||||
for (i = 0; i < (istop >> 6); i++)
|
||||
{
|
||||
LD_UB4(rp, 16, src0, src1, src2, src3);
|
||||
LD_UB4(pp, 16, src4, src5, src6, src7);
|
||||
pp += 64;
|
||||
|
||||
ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
|
||||
src0, src1, src2, src3);
|
||||
|
||||
ST_UB4(src0, src1, src2, src3, rp, 16);
|
||||
rp += 64;
|
||||
}
|
||||
|
||||
if (istop & 0x3F)
|
||||
{
|
||||
cnt32 = istop & 0x20;
|
||||
cnt16 = istop & 0x10;
|
||||
cnt = istop & 0xF;
|
||||
|
||||
if(cnt32)
|
||||
{
|
||||
if (cnt16 && cnt)
|
||||
{
|
||||
LD_UB4(rp, 16, src0, src1, src2, src3);
|
||||
LD_UB4(pp, 16, src4, src5, src6, src7);
|
||||
|
||||
ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
|
||||
src0, src1, src2, src3);
|
||||
|
||||
ST_UB4(src0, src1, src2, src3, rp, 16);
|
||||
rp += 64;
|
||||
}
|
||||
else if (cnt16 || cnt)
|
||||
{
|
||||
LD_UB2(rp, 16, src0, src1);
|
||||
LD_UB2(pp, 16, src4, src5);
|
||||
pp += 32;
|
||||
src2 = LD_UB(rp + 32);
|
||||
src6 = LD_UB(pp);
|
||||
|
||||
ADD3(src0, src4, src1, src5, src2, src6, src0, src1, src2);
|
||||
|
||||
ST_UB2(src0, src1, rp, 16);
|
||||
rp += 32;
|
||||
ST_UB(src2, rp);
|
||||
rp += 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
LD_UB2(rp, 16, src0, src1);
|
||||
LD_UB2(pp, 16, src4, src5);
|
||||
|
||||
ADD2(src0, src4, src1, src5, src0, src1);
|
||||
|
||||
ST_UB2(src0, src1, rp, 16);
|
||||
rp += 32;
|
||||
}
|
||||
}
|
||||
else if (cnt16 && cnt)
|
||||
{
|
||||
LD_UB2(rp, 16, src0, src1);
|
||||
LD_UB2(pp, 16, src4, src5);
|
||||
|
||||
ADD2(src0, src4, src1, src5, src0, src1);
|
||||
|
||||
ST_UB2(src0, src1, rp, 16);
|
||||
rp += 32;
|
||||
}
|
||||
else if (cnt16 || cnt)
|
||||
{
|
||||
src0 = LD_UB(rp);
|
||||
src4 = LD_UB(pp);
|
||||
pp += 16;
|
||||
|
||||
src0 += src4;
|
||||
|
||||
ST_UB(src0, rp);
|
||||
rp += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_sub4_msa(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_size_t count;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
png_bytep src = row;
|
||||
png_bytep nxt = row + 4;
|
||||
int32_t inp0;
|
||||
v16u8 src0, src1, src2, src3, src4;
|
||||
v16u8 dst0, dst1;
|
||||
v16u8 zero = { 0 };
|
||||
|
||||
istop -= 4;
|
||||
|
||||
inp0 = LW(src);
|
||||
src += 4;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
|
||||
for (count = 0; count < istop; count += 16)
|
||||
{
|
||||
src1 = LD_UB(src);
|
||||
src += 16;
|
||||
|
||||
src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 4);
|
||||
src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 8);
|
||||
src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 12);
|
||||
src1 += src0;
|
||||
src2 += src1;
|
||||
src3 += src2;
|
||||
src4 += src3;
|
||||
src0 = src4;
|
||||
ILVEV_W2_UB(src1, src2, src3, src4, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
|
||||
|
||||
ST_UB(dst0, nxt);
|
||||
nxt += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_sub3_msa(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_size_t count;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
png_bytep src = row;
|
||||
png_bytep nxt = row + 3;
|
||||
int64_t out0;
|
||||
int32_t inp0, out1;
|
||||
v16u8 src0, src1, src2, src3, src4, dst0, dst1;
|
||||
v16u8 zero = { 0 };
|
||||
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
|
||||
|
||||
istop -= 3;
|
||||
|
||||
inp0 = LW(src);
|
||||
src += 3;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
|
||||
for (count = 0; count < istop; count += 12)
|
||||
{
|
||||
src1 = LD_UB(src);
|
||||
src += 12;
|
||||
|
||||
src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 3);
|
||||
src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 6);
|
||||
src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 9);
|
||||
src1 += src0;
|
||||
src2 += src1;
|
||||
src3 += src2;
|
||||
src4 += src3;
|
||||
src0 = src4;
|
||||
VSHF_B2_UB(src1, src2, src3, src4, mask0, mask0, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
|
||||
out0 = __msa_copy_s_d((v2i64) dst0, 0);
|
||||
out1 = __msa_copy_s_w((v4i32) dst0, 2);
|
||||
|
||||
SD(out0, nxt);
|
||||
nxt += 8;
|
||||
SW(out1, nxt);
|
||||
nxt += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg4_msa(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_size_t i;
|
||||
png_bytep src = row;
|
||||
png_bytep nxt = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_size_t istop = row_info->rowbytes - 4;
|
||||
int32_t inp0, inp1, out0;
|
||||
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
|
||||
v16u8 zero = { 0 };
|
||||
|
||||
inp0 = LW(pp);
|
||||
pp += 4;
|
||||
inp1 = LW(src);
|
||||
src += 4;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
|
||||
src0 = (v16u8) MSA_SRLI_B(src0, 1);
|
||||
src1 += src0;
|
||||
out0 = __msa_copy_s_w((v4i32) src1, 0);
|
||||
SW(out0, nxt);
|
||||
nxt += 4;
|
||||
|
||||
for (i = 0; i < istop; i += 16)
|
||||
{
|
||||
src2 = LD_UB(pp);
|
||||
pp += 16;
|
||||
src6 = LD_UB(src);
|
||||
src += 16;
|
||||
|
||||
SLDI_B2_0_UB(src2, src6, src3, src7, 4);
|
||||
SLDI_B2_0_UB(src2, src6, src4, src8, 8);
|
||||
SLDI_B2_0_UB(src2, src6, src5, src9, 12);
|
||||
src2 = __msa_ave_u_b(src2, src1);
|
||||
src6 += src2;
|
||||
src3 = __msa_ave_u_b(src3, src6);
|
||||
src7 += src3;
|
||||
src4 = __msa_ave_u_b(src4, src7);
|
||||
src8 += src4;
|
||||
src5 = __msa_ave_u_b(src5, src8);
|
||||
src9 += src5;
|
||||
src1 = src9;
|
||||
ILVEV_W2_UB(src6, src7, src8, src9, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
|
||||
|
||||
ST_UB(dst0, nxt);
|
||||
nxt += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg3_msa(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_size_t i;
|
||||
png_bytep src = row;
|
||||
png_bytep nxt = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_size_t istop = row_info->rowbytes - 3;
|
||||
int64_t out0;
|
||||
int32_t inp0, inp1, out1;
|
||||
int16_t out2;
|
||||
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
|
||||
v16u8 zero = { 0 };
|
||||
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
|
||||
|
||||
inp0 = LW(pp);
|
||||
pp += 3;
|
||||
inp1 = LW(src);
|
||||
src += 3;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
|
||||
src0 = (v16u8) MSA_SRLI_B(src0, 1);
|
||||
src1 += src0;
|
||||
out2 = __msa_copy_s_h((v8i16) src1, 0);
|
||||
SH(out2, nxt);
|
||||
nxt += 2;
|
||||
nxt[0] = src1[2];
|
||||
nxt++;
|
||||
|
||||
for (i = 0; i < istop; i += 12)
|
||||
{
|
||||
src2 = LD_UB(pp);
|
||||
pp += 12;
|
||||
src6 = LD_UB(src);
|
||||
src += 12;
|
||||
|
||||
SLDI_B2_0_UB(src2, src6, src3, src7, 3);
|
||||
SLDI_B2_0_UB(src2, src6, src4, src8, 6);
|
||||
SLDI_B2_0_UB(src2, src6, src5, src9, 9);
|
||||
src2 = __msa_ave_u_b(src2, src1);
|
||||
src6 += src2;
|
||||
src3 = __msa_ave_u_b(src3, src6);
|
||||
src7 += src3;
|
||||
src4 = __msa_ave_u_b(src4, src7);
|
||||
src8 += src4;
|
||||
src5 = __msa_ave_u_b(src5, src8);
|
||||
src9 += src5;
|
||||
src1 = src9;
|
||||
VSHF_B2_UB(src6, src7, src8, src9, mask0, mask0, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
|
||||
out0 = __msa_copy_s_d((v2i64) dst0, 0);
|
||||
out1 = __msa_copy_s_w((v4i32) dst0, 2);
|
||||
|
||||
SD(out0, nxt);
|
||||
nxt += 8;
|
||||
SW(out1, nxt);
|
||||
nxt += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth4_msa(png_row_infop row_info,
|
||||
png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
int32_t count, rp_end;
|
||||
png_bytep nxt;
|
||||
png_const_bytep prev_nxt;
|
||||
int32_t inp0, inp1, res0;
|
||||
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9;
|
||||
v16u8 src10, src11, src12, src13, dst0, dst1;
|
||||
v8i16 vec0, vec1, vec2;
|
||||
v16u8 zero = { 0 };
|
||||
|
||||
nxt = row;
|
||||
prev_nxt = prev_row;
|
||||
|
||||
inp0 = LW(nxt);
|
||||
inp1 = LW(prev_nxt);
|
||||
prev_nxt += 4;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
|
||||
|
||||
src1 += src0;
|
||||
res0 = __msa_copy_s_w((v4i32) src1, 0);
|
||||
|
||||
SW(res0, nxt);
|
||||
nxt += 4;
|
||||
|
||||
/* Remainder */
|
||||
rp_end = row_info->rowbytes - 4;
|
||||
|
||||
for (count = 0; count < rp_end; count += 16)
|
||||
{
|
||||
src2 = LD_UB(prev_nxt);
|
||||
prev_nxt += 16;
|
||||
src6 = LD_UB(prev_row);
|
||||
prev_row += 16;
|
||||
src10 = LD_UB(nxt);
|
||||
|
||||
SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 4);
|
||||
SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 8);
|
||||
SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 12);
|
||||
ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
|
||||
ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
|
||||
ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
|
||||
ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
|
||||
src1 = src13;
|
||||
ILVEV_W2_UB(src10, src11, src12, src1, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
|
||||
|
||||
ST_UB(dst0, nxt);
|
||||
nxt += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth3_msa(png_row_infop row_info,
|
||||
png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
int32_t count, rp_end;
|
||||
png_bytep nxt;
|
||||
png_const_bytep prev_nxt;
|
||||
int64_t out0;
|
||||
int32_t inp0, inp1, out1;
|
||||
int16_t out2;
|
||||
v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
|
||||
v16u8 src10, src11, src12, src13;
|
||||
v8i16 vec0, vec1, vec2;
|
||||
v16u8 zero = { 0 };
|
||||
v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
|
||||
|
||||
nxt = row;
|
||||
prev_nxt = prev_row;
|
||||
|
||||
inp0 = LW(nxt);
|
||||
inp1 = LW(prev_nxt);
|
||||
prev_nxt += 3;
|
||||
src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
|
||||
src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
|
||||
|
||||
src1 += src0;
|
||||
out2 = __msa_copy_s_h((v8i16) src1, 0);
|
||||
|
||||
SH(out2, nxt);
|
||||
nxt += 2;
|
||||
nxt[0] = src1[2];
|
||||
nxt++;
|
||||
|
||||
/* Remainder */
|
||||
rp_end = row_info->rowbytes - 3;
|
||||
|
||||
for (count = 0; count < rp_end; count += 12)
|
||||
{
|
||||
src2 = LD_UB(prev_nxt);
|
||||
prev_nxt += 12;
|
||||
src6 = LD_UB(prev_row);
|
||||
prev_row += 12;
|
||||
src10 = LD_UB(nxt);
|
||||
|
||||
SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 3);
|
||||
SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 6);
|
||||
SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 9);
|
||||
ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
|
||||
ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
|
||||
ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
|
||||
ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
|
||||
HSUB_UB2_SH(vec0, vec1, vec0, vec1);
|
||||
vec2 = vec0 + vec1;
|
||||
ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
|
||||
CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
|
||||
src1 = src13;
|
||||
VSHF_B2_UB(src10, src11, src12, src13, mask0, mask0, dst0, dst1);
|
||||
dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
|
||||
out0 = __msa_copy_s_d((v2i64) dst0, 0);
|
||||
out1 = __msa_copy_s_w((v4i32) dst0, 2);
|
||||
|
||||
SD(out0, nxt);
|
||||
nxt += 8;
|
||||
SW(out1, nxt);
|
||||
nxt += 4;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PNG_MIPS_MSA_OPT > 0 */
|
||||
#endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 (intrinsics) */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
|
||||
/* mips_init.c - MSA optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2016 Glenn Randers-Pehrson
|
||||
* Written by Mandar Sahastrabuddhe, 2016.
|
||||
* Last changed in libpng 1.6.25 [September 1, 2016]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
|
||||
* called.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
#if PNG_MIPS_MSA_OPT > 0
|
||||
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do run-time checks */
|
||||
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||
* run-time checks for CPU features if at all possible. In the case of the MIPS
|
||||
* MSA instructions there is no processor-specific way of detecting the
|
||||
* presence of the required support, therefore run-time detection is extremely
|
||||
* OS specific.
|
||||
*
|
||||
* You may set the macro PNG_MIPS_MSA_FILE to the file name of file containing
|
||||
* a fragment of C source code which defines the png_have_msa function. There
|
||||
* are a number of implementations in contrib/mips-msa, but the only one that
|
||||
* has partial support is contrib/mips-msa/linux.c - a generic Linux
|
||||
* implementation which reads /proc/cpufino.
|
||||
*/
|
||||
#ifndef PNG_MIPS_MSA_FILE
|
||||
# ifdef __linux__
|
||||
# define PNG_MIPS_MSA_FILE "contrib/mips-msa/linux.c"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_MIPS_MSA_FILE
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
static int png_have_msa(png_structp png_ptr);
|
||||
#include PNG_MIPS_MSA_FILE
|
||||
|
||||
#else /* PNG_MIPS_MSA_FILE */
|
||||
# error "PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks"
|
||||
#endif /* PNG_MIPS_MSA_FILE */
|
||||
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
|
||||
|
||||
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
|
||||
#endif
|
||||
|
||||
void
|
||||
png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The switch statement is compiled in for MIPS_MSA_API, the call to
|
||||
* png_have_msa is compiled in for MIPS_MSA_CHECK. If both are defined
|
||||
* the check is only performed if the API has not set the MSA option on
|
||||
* or off explicitly. In this case the check controls what happens.
|
||||
*/
|
||||
|
||||
#ifdef PNG_MIPS_MSA_API_SUPPORTED
|
||||
switch ((pp->options >> PNG_MIPS_MSA) & 3)
|
||||
{
|
||||
case PNG_OPTION_UNSET:
|
||||
/* Allow the run-time check to execute if it has been enabled -
|
||||
* thus both API and CHECK can be turned on. If it isn't supported
|
||||
* this case will fall through to the 'default' below, which just
|
||||
* returns.
|
||||
*/
|
||||
#endif /* PNG_MIPS_MSA_API_SUPPORTED */
|
||||
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED
|
||||
{
|
||||
static volatile sig_atomic_t no_msa = -1; /* not checked */
|
||||
|
||||
if (no_msa < 0)
|
||||
no_msa = !png_have_msa(pp);
|
||||
|
||||
if (no_msa)
|
||||
return;
|
||||
}
|
||||
#ifdef PNG_MIPS_MSA_API_SUPPORTED
|
||||
break;
|
||||
#endif
|
||||
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
|
||||
|
||||
#ifdef PNG_MIPS_MSA_API_SUPPORTED
|
||||
default: /* OFF or INVALID */
|
||||
return;
|
||||
|
||||
case PNG_OPTION_ON:
|
||||
/* Option turned on */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IMPORTANT: any new external functions used here must be declared using
|
||||
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||
* 'prefix' option to configure works:
|
||||
*
|
||||
* ./configure --with-libpng-prefix=foobar_
|
||||
*
|
||||
* Verify you have got this right by running the above command, doing a build
|
||||
* and examining pngprefix.h; it must contain a #define for every external
|
||||
* function you add. (Notice that this happens automatically for the
|
||||
* initialization function.)
|
||||
*/
|
||||
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_msa;
|
||||
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_msa;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa;
|
||||
}
|
||||
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa;
|
||||
}
|
||||
}
|
||||
#endif /* PNG_MIPS_MSA_OPT > 0 */
|
||||
#endif /* READ */
|
||||
4614
src/png/libpng/png.c
4614
src/png/libpng/png.c
File diff suppressed because it is too large
Load diff
3278
src/png/libpng/png.h
3278
src/png/libpng/png.h
File diff suppressed because it is too large
Load diff
|
|
@ -1,622 +0,0 @@
|
|||
|
||||
/* pngconf.h - machine configurable file for libpng
|
||||
*
|
||||
* libpng version 1.6.34, September 29, 2017
|
||||
*
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 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
|
||||
*
|
||||
* 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
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
|
||||
|
||||
/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
|
||||
* compiler for correct compilation. The following header files are required by
|
||||
* the standard. If your compiler doesn't provide these header files, or they
|
||||
* do not match the standard, you will need to provide/improve them.
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Library header files. These header files are all defined by ISOC90; libpng
|
||||
* expects conformant implementations, however, an ISOC90 conformant system need
|
||||
* not provide these header files if the functionality cannot be implemented.
|
||||
* In this case it will be necessary to disable the relevant parts of libpng in
|
||||
* the build of pnglibconf.h.
|
||||
*
|
||||
* Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
|
||||
* include this unnecessary header file.
|
||||
*/
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
/* Required for the definition of FILE: */
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
/* Required for the definition of jmp_buf and the declaration of longjmp: */
|
||||
# include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_CONVERT_tIME_SUPPORTED
|
||||
/* Required for struct tm: */
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
|
||||
* PNG_NO_CONST; this is no longer supported except for data declarations which
|
||||
* apparently still cause problems in 2011 on some compilers.
|
||||
*/
|
||||
#define PNG_CONST const /* backward compatibility only */
|
||||
|
||||
/* This controls optimization of the reading of 16-bit 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 when 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 was used in versions of libpng prior to 1.6.0 to protect
|
||||
* against legacy (pre ISOC90) compilers that did not understand function
|
||||
* prototypes. It is not required for modern C compilers.
|
||||
*/
|
||||
#ifndef PNGARG
|
||||
# define PNGARG(arglist) arglist
|
||||
#endif
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* 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. Not used in the
|
||||
* public header files; see pngpriv.h for how it is used
|
||||
* in the libpng build.
|
||||
*
|
||||
* 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 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__)
|
||||
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
|
||||
* MinGW on any architecture currently supported by Windows. 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
|
||||
/* If this line results in an error __stdcall is not understood and
|
||||
* PNG_API_RULE should not have been set to '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 */
|
||||
# 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
|
||||
|
||||
/* PNG_IMPEXP may be set on the compilation system command line or (if not set)
|
||||
* then in an internal header file when building the library, otherwise (when
|
||||
* using the library) it is set here.
|
||||
*/
|
||||
#ifndef PNG_IMPEXP
|
||||
# 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
|
||||
|
||||
# ifndef PNG_IMPEXP
|
||||
# define PNG_IMPEXP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
#ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
|
||||
#endif
|
||||
|
||||
/* 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), \
|
||||
PNG_LINKAGE_API 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.
|
||||
*
|
||||
* 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. Disabling these removes the warnings but may also produce
|
||||
* less efficient code.
|
||||
*/
|
||||
# if defined(__clang__) && defined(__has_attribute)
|
||||
/* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
|
||||
# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# if !defined(PNG_PRIVATE)
|
||||
# ifdef __has_extension
|
||||
# if __has_extension(attribute_unavailable_with_message)
|
||||
# define PNG_PRIVATE __attribute__((__unavailable__(\
|
||||
"This function is not exported by libpng.")))
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
|
||||
# elif defined(__GNUC__)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if __GNUC__ >= 3
|
||||
# ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __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
|
||||
# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
|
||||
# endif /* __GNUC__ >= 3 */
|
||||
|
||||
# elif 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_ALLOCATED
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_ALLOCATED __declspec(restrict)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# elif defined(__WATCOMC__)
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
#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_PRIVATE
|
||||
# define PNG_PRIVATE /* This is a private libpng function */
|
||||
#endif
|
||||
#ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT /* The C99 "restrict" feature */
|
||||
#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
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE
|
||||
/* Some typedefs to get us started. These should be safe on most of the common
|
||||
* platforms.
|
||||
*
|
||||
* png_uint_32 and png_int_32 may, currently, be larger than required to hold a
|
||||
* 32-bit value however this is not normally advisable.
|
||||
*
|
||||
* png_uint_16 and png_int_16 should always be two bytes in size - this is
|
||||
* verified at library build time.
|
||||
*
|
||||
* png_byte must always be one byte in size.
|
||||
*
|
||||
* The checks below use constants from limits.h, as defined by the ISOC90
|
||||
* standard.
|
||||
*/
|
||||
#if CHAR_BIT == 8 && UCHAR_MAX == 255
|
||||
typedef unsigned char png_byte;
|
||||
#else
|
||||
# error "libpng requires 8-bit bytes"
|
||||
#endif
|
||||
|
||||
#if INT_MIN == -32768 && INT_MAX == 32767
|
||||
typedef int png_int_16;
|
||||
#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
|
||||
typedef short png_int_16;
|
||||
#else
|
||||
# error "libpng requires a signed 16-bit type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX == 65535
|
||||
typedef unsigned int png_uint_16;
|
||||
#elif USHRT_MAX == 65535
|
||||
typedef unsigned short png_uint_16;
|
||||
#else
|
||||
# error "libpng requires an unsigned 16-bit type"
|
||||
#endif
|
||||
|
||||
#if INT_MIN < -2147483646 && INT_MAX > 2147483646
|
||||
typedef int png_int_32;
|
||||
#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
|
||||
typedef long int png_int_32;
|
||||
#else
|
||||
# error "libpng requires a signed 32-bit (or more) type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX > 4294967294U
|
||||
typedef unsigned int png_uint_32;
|
||||
#elif ULONG_MAX > 4294967294U
|
||||
typedef unsigned long int png_uint_32;
|
||||
#else
|
||||
# error "libpng requires an unsigned 32-bit (or more) type"
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
|
||||
* requires an ISOC90 compiler and relies on consistent behavior of sizeof.
|
||||
*/
|
||||
typedef size_t png_size_t;
|
||||
typedef ptrdiff_t png_ptrdiff_t;
|
||||
|
||||
/* libpng needs to know the maximum value of 'size_t' and this controls the
|
||||
* definition of png_alloc_size_t, below. This maximum value of size_t limits
|
||||
* but does not control the maximum allocations the library makes - there is
|
||||
* direct application control of this through png_set_user_limits().
|
||||
*/
|
||||
#ifndef PNG_SMALL_SIZE_T
|
||||
/* Compiler specific tests for systems where size_t is known to be less than
|
||||
* 32 bits (some of these systems may no longer work because of the lack of
|
||||
* 'far' support; see above.)
|
||||
*/
|
||||
# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
|
||||
(defined(_MSC_VER) && defined(MAXSEG_64K))
|
||||
# define PNG_SMALL_SIZE_T
|
||||
# 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 not to use
|
||||
* them at all so that the compiler can complain when something turns out to be
|
||||
* problematic.
|
||||
*
|
||||
* Casts in the other direction (from png_alloc_size_t to png_size_t or
|
||||
* png_uint_32) should be explicitly applied; however, we do not expect to
|
||||
* encounter practical situations that require such conversions.
|
||||
*
|
||||
* PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
|
||||
* 4294967295 - i.e. less than the maximum value of png_uint_32.
|
||||
*/
|
||||
#ifdef PNG_SMALL_SIZE_T
|
||||
typedef png_uint_32 png_alloc_size_t;
|
||||
#else
|
||||
typedef png_size_t png_alloc_size_t;
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
|
||||
* implementations of Intel CPU specific support of user-mode segmented address
|
||||
* spaces, where 16-bit pointers address more than 65536 bytes of memory using
|
||||
* separate 'segment' registers. The implementation requires two different
|
||||
* types of pointer (only one of which includes the segment value.)
|
||||
*
|
||||
* If required this support is available in version 1.2 of libpng and may be
|
||||
* available in versions through 1.5, although the correctness of the code has
|
||||
* not been verified recently.
|
||||
*/
|
||||
|
||||
/* Typedef for floating-point numbers that are converted 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 * png_voidp;
|
||||
typedef const void * png_const_voidp;
|
||||
typedef png_byte * png_bytep;
|
||||
typedef const png_byte * png_const_bytep;
|
||||
typedef png_uint_32 * png_uint_32p;
|
||||
typedef const png_uint_32 * png_const_uint_32p;
|
||||
typedef png_int_32 * png_int_32p;
|
||||
typedef const png_int_32 * png_const_int_32p;
|
||||
typedef png_uint_16 * png_uint_16p;
|
||||
typedef const png_uint_16 * png_const_uint_16p;
|
||||
typedef png_int_16 * png_int_16p;
|
||||
typedef const png_int_16 * png_const_int_16p;
|
||||
typedef char * png_charp;
|
||||
typedef const char * png_const_charp;
|
||||
typedef png_fixed_point * png_fixed_point_p;
|
||||
typedef const png_fixed_point * png_const_fixed_point_p;
|
||||
typedef png_size_t * png_size_tp;
|
||||
typedef const png_size_t * png_const_size_tp;
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
typedef FILE * png_FILE_p;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * png_doublep;
|
||||
typedef const double * png_const_doublep;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers; i.e. arrays */
|
||||
typedef png_byte * * png_bytepp;
|
||||
typedef png_uint_32 * * png_uint_32pp;
|
||||
typedef png_int_32 * * png_int_32pp;
|
||||
typedef png_uint_16 * * png_uint_16pp;
|
||||
typedef png_int_16 * * png_int_16pp;
|
||||
typedef const char * * png_const_charpp;
|
||||
typedef char * * png_charpp;
|
||||
typedef png_fixed_point * * png_fixed_point_pp;
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * * png_doublepp;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers to pointers; i.e., pointer to array */
|
||||
typedef char * * * png_charppp;
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
#endif /* PNGCONF_H */
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
|
||||
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
|
||||
*
|
||||
* Last changed in libpng 1.6.8 [December 19, 2013]
|
||||
* Copyright (c) 1998-2002,2004,2006-2013 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
|
||||
*/
|
||||
|
||||
/* 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' 3-space indentations (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 <crtdbg.h>
|
||||
# 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 <stdio.h> /* not included yet */
|
||||
# endif
|
||||
# ifndef PNG_DEBUG_FILE
|
||||
# define PNG_DEBUG_FILE stderr
|
||||
# endif /* PNG_DEBUG_FILE */
|
||||
|
||||
# if (PNG_DEBUG > 1)
|
||||
# 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 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
|
||||
} 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 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),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 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),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 */
|
||||
|
|
@ -1,963 +0,0 @@
|
|||
|
||||
/* pngerror.c - stub functions for i/o and memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.6.31 [July 27, 2017]
|
||||
* Copyright (c) 1998-2002,2004,2006-2017 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_const_structrp png_ptr,
|
||||
png_const_charp error_message)),PNG_NORETURN);
|
||||
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
static void /* PRIVATE */
|
||||
png_default_warning PNGARG((png_const_structrp png_ptr,
|
||||
png_const_charp warning_message));
|
||||
#endif /* WARNINGS */
|
||||
|
||||
/* 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_const_structrp 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)) != 0)
|
||||
{
|
||||
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) != 0)
|
||||
{
|
||||
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) != 0)
|
||||
{
|
||||
msg[0] = '0';
|
||||
msg[1] = '\0';
|
||||
error_message = msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (png_ptr != NULL && png_ptr->error_fn != NULL)
|
||||
(*(png_ptr->error_fn))(png_constcast(png_structrp,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_const_structrp png_ptr),PNG_NORETURN)
|
||||
{
|
||||
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
|
||||
* erroneously as '\0', instead of the empty string "". This was
|
||||
* apparently an error, introduced in libpng-1.2.20, and png_default_error
|
||||
* will crash in this case.
|
||||
*/
|
||||
if (png_ptr != NULL && png_ptr->error_fn != NULL)
|
||||
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
|
||||
|
||||
/* If the custom handler doesn't exist, or if it returns,
|
||||
use the default handler, which will not return. */
|
||||
png_default_error(png_ptr, "");
|
||||
}
|
||||
#endif /* ERROR_TEXT */
|
||||
|
||||
/* Utility to safely appends strings to a buffer. This never errors out so
|
||||
* error checking is not required in the caller.
|
||||
*/
|
||||
size_t
|
||||
png_safecat(png_charp buffer, size_t bufsize, size_t pos,
|
||||
png_const_charp string)
|
||||
{
|
||||
if (buffer != NULL && pos < bufsize)
|
||||
{
|
||||
if (string != NULL)
|
||||
while (*string != '\0' && pos < bufsize-1)
|
||||
buffer[pos++] = *string++;
|
||||
|
||||
buffer[pos] = '\0';
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
|
||||
/* Utility to dump an unsigned value into a buffer, given a start pointer and
|
||||
* and end pointer (which should point just *beyond* the end of the buffer!)
|
||||
* Returns the pointer to the start of the formatted string.
|
||||
*/
|
||||
png_charp
|
||||
png_format_number(png_const_charp start, png_charp end, int format,
|
||||
png_alloc_size_t number)
|
||||
{
|
||||
int count = 0; /* number of digits output */
|
||||
int mincount = 1; /* minimum number required */
|
||||
int output = 0; /* digit output (for the fixed point format) */
|
||||
|
||||
*--end = '\0';
|
||||
|
||||
/* This is written so that the loop always runs at least once, even with
|
||||
* number zero.
|
||||
*/
|
||||
while (end > start && (number != 0 || count < mincount))
|
||||
{
|
||||
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PNG_NUMBER_FORMAT_fixed:
|
||||
/* Needs five digits (the fraction) */
|
||||
mincount = 5;
|
||||
if (output != 0 || number % 10 != 0)
|
||||
{
|
||||
*--end = digits[number % 10];
|
||||
output = 1;
|
||||
}
|
||||
number /= 10;
|
||||
break;
|
||||
|
||||
case PNG_NUMBER_FORMAT_02u:
|
||||
/* Expects at least 2 digits. */
|
||||
mincount = 2;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PNG_NUMBER_FORMAT_u:
|
||||
*--end = digits[number % 10];
|
||||
number /= 10;
|
||||
break;
|
||||
|
||||
case PNG_NUMBER_FORMAT_02x:
|
||||
/* This format expects at least two digits */
|
||||
mincount = 2;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PNG_NUMBER_FORMAT_x:
|
||||
*--end = digits[number & 0xf];
|
||||
number >>= 4;
|
||||
break;
|
||||
|
||||
default: /* an error */
|
||||
number = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Keep track of the number of digits added */
|
||||
++count;
|
||||
|
||||
/* Float a fixed number here: */
|
||||
if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
|
||||
{
|
||||
/* End of the fraction, but maybe nothing was output? In that case
|
||||
* drop the decimal point. If the number is a true zero handle that
|
||||
* here.
|
||||
*/
|
||||
if (output != 0)
|
||||
*--end = '.';
|
||||
else if (number == 0) /* and !output */
|
||||
*--end = '0';
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
/* This function is called whenever there is a non-fatal error. This function
|
||||
* should not be changed. If there is a need to handle warnings differently,
|
||||
* 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_const_structrp 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)) != 0)
|
||||
#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_constcast(png_structrp,png_ptr),
|
||||
warning_message + offset);
|
||||
else
|
||||
png_default_warning(png_ptr, warning_message + offset);
|
||||
}
|
||||
|
||||
/* These functions support 'formatted' warning messages with up to
|
||||
* PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter
|
||||
* is introduced by @<number>, where 'number' starts at 1. This follows the
|
||||
* standard established by X/Open for internationalizable error messages.
|
||||
*/
|
||||
void
|
||||
png_warning_parameter(png_warning_parameters p, int number,
|
||||
png_const_charp string)
|
||||
{
|
||||
if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
|
||||
(void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
|
||||
}
|
||||
|
||||
void
|
||||
png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
|
||||
png_alloc_size_t value)
|
||||
{
|
||||
char buffer[PNG_NUMBER_BUFFER_SIZE];
|
||||
png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
|
||||
}
|
||||
|
||||
void
|
||||
png_warning_parameter_signed(png_warning_parameters p, int number, int format,
|
||||
png_int_32 value)
|
||||
{
|
||||
png_alloc_size_t u;
|
||||
png_charp str;
|
||||
char buffer[PNG_NUMBER_BUFFER_SIZE];
|
||||
|
||||
/* Avoid overflow by doing the negate in a png_alloc_size_t: */
|
||||
u = (png_alloc_size_t)value;
|
||||
if (value < 0)
|
||||
u = ~u + 1;
|
||||
|
||||
str = PNG_FORMAT_NUMBER(buffer, format, u);
|
||||
|
||||
if (value < 0 && str > buffer)
|
||||
*--str = '-';
|
||||
|
||||
png_warning_parameter(p, number, str);
|
||||
}
|
||||
|
||||
void
|
||||
png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
|
||||
png_const_charp message)
|
||||
{
|
||||
/* The internal buffer is just 192 bytes - enough for all our messages,
|
||||
* overflow doesn't happen because this code checks! If someone figures
|
||||
* out how to send us a message longer than 192 bytes, all that will
|
||||
* happen is that the message will be truncated appropriately.
|
||||
*/
|
||||
size_t i = 0; /* Index in the msg[] buffer: */
|
||||
char msg[192];
|
||||
|
||||
/* Each iteration through the following loop writes at most one character
|
||||
* to msg[i++] then returns here to validate that there is still space for
|
||||
* the trailing '\0'. It may (in the case of a parameter) read more than
|
||||
* one character from message[]; it must check for '\0' and continue to the
|
||||
* test if it finds the end of string.
|
||||
*/
|
||||
while (i<(sizeof msg)-1 && *message != '\0')
|
||||
{
|
||||
/* '@' at end of string is now just printed (previously it was skipped);
|
||||
* it is an error in the calling code to terminate the string with @.
|
||||
*/
|
||||
if (p != NULL && *message == '@' && message[1] != '\0')
|
||||
{
|
||||
int parameter_char = *++message; /* Consume the '@' */
|
||||
static const char valid_parameters[] = "123456789";
|
||||
int parameter = 0;
|
||||
|
||||
/* Search for the parameter digit, the index in the string is the
|
||||
* parameter to use.
|
||||
*/
|
||||
while (valid_parameters[parameter] != parameter_char &&
|
||||
valid_parameters[parameter] != '\0')
|
||||
++parameter;
|
||||
|
||||
/* If the parameter digit is out of range it will just get printed. */
|
||||
if (parameter < PNG_WARNING_PARAMETER_COUNT)
|
||||
{
|
||||
/* Append this parameter */
|
||||
png_const_charp parm = p[parameter];
|
||||
png_const_charp pend = p[parameter] + (sizeof p[parameter]);
|
||||
|
||||
/* No need to copy the trailing '\0' here, but there is no guarantee
|
||||
* that parm[] has been initialized, so there is no guarantee of a
|
||||
* trailing '\0':
|
||||
*/
|
||||
while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
|
||||
msg[i++] = *parm++;
|
||||
|
||||
/* Consume the parameter digit too: */
|
||||
++message;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* else not a parameter and there is a character after the @ sign; just
|
||||
* copy that. This is known not to be '\0' because of the test above.
|
||||
*/
|
||||
}
|
||||
|
||||
/* At this point *message can't be '\0', even in the bad parameter case
|
||||
* above where there is a lone '@' at the end of the message string.
|
||||
*/
|
||||
msg[i++] = *message++;
|
||||
}
|
||||
|
||||
/* i is always less than (sizeof msg), so: */
|
||||
msg[i] = '\0';
|
||||
|
||||
/* And this is the formatted message. It may be larger than
|
||||
* PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
|
||||
* are not (currently) formatted.
|
||||
*/
|
||||
png_warning(png_ptr, msg);
|
||||
}
|
||||
#endif /* WARNINGS */
|
||||
|
||||
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
|
||||
void PNGAPI
|
||||
png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
|
||||
{
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
|
||||
png_ptr->chunk_name != 0)
|
||||
png_chunk_warning(png_ptr, error_message);
|
||||
else
|
||||
# endif
|
||||
png_warning(png_ptr, error_message);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
|
||||
png_ptr->chunk_name != 0)
|
||||
png_chunk_error(png_ptr, error_message);
|
||||
else
|
||||
# endif
|
||||
png_error(png_ptr, error_message);
|
||||
}
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(error_message)
|
||||
# endif
|
||||
}
|
||||
|
||||
void /* PRIVATE */
|
||||
png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
|
||||
png_warning(png_ptr, error_message);
|
||||
else
|
||||
png_error(png_ptr, error_message);
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(error_message)
|
||||
# endif
|
||||
}
|
||||
|
||||
void /* PRIVATE */
|
||||
png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
|
||||
png_warning(png_ptr, error_message);
|
||||
else
|
||||
png_error(png_ptr, error_message);
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(error_message)
|
||||
# endif
|
||||
}
|
||||
#endif /* BENIGN_ERRORS */
|
||||
|
||||
#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
|
||||
#if defined(PNG_WARNINGS_SUPPORTED) || \
|
||||
(defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
|
||||
/* 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,
|
||||
* which 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'
|
||||
};
|
||||
|
||||
static void /* PRIVATE */
|
||||
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
|
||||
error_message)
|
||||
{
|
||||
png_uint_32 chunk_name = png_ptr->chunk_name;
|
||||
int iout = 0, ishift = 24;
|
||||
|
||||
while (ishift >= 0)
|
||||
{
|
||||
int c = (int)(chunk_name >> ishift) & 0xff;
|
||||
|
||||
ishift -= 8;
|
||||
if (isnonalpha(c) != 0)
|
||||
{
|
||||
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++] = (char)c;
|
||||
}
|
||||
}
|
||||
|
||||
if (error_message == NULL)
|
||||
buffer[iout] = '\0';
|
||||
|
||||
else
|
||||
{
|
||||
int iin = 0;
|
||||
|
||||
buffer[iout++] = ':';
|
||||
buffer[iout++] = ' ';
|
||||
|
||||
while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
|
||||
buffer[iout++] = error_message[iin++];
|
||||
|
||||
/* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
|
||||
buffer[iout] = '\0';
|
||||
}
|
||||
}
|
||||
#endif /* WARNINGS || ERROR_TEXT */
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
|
||||
PNG_FUNCTION(void,PNGAPI
|
||||
png_chunk_error,(png_const_structrp 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 /* READ && ERROR_TEXT */
|
||||
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
void PNGAPI
|
||||
png_chunk_warning(png_const_structrp 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 /* WARNINGS */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
|
||||
void PNGAPI
|
||||
png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
|
||||
error_message)
|
||||
{
|
||||
if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
|
||||
png_chunk_warning(png_ptr, error_message);
|
||||
|
||||
else
|
||||
png_chunk_error(png_ptr, error_message);
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(error_message)
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#endif /* READ */
|
||||
|
||||
void /* PRIVATE */
|
||||
png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
|
||||
{
|
||||
# ifndef PNG_WARNINGS_SUPPORTED
|
||||
PNG_UNUSED(message)
|
||||
# endif
|
||||
|
||||
/* This is always supported, but for just read or just write it
|
||||
* unconditionally does the right thing.
|
||||
*/
|
||||
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
|
||||
# endif
|
||||
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
{
|
||||
if (error < PNG_CHUNK_ERROR)
|
||||
png_chunk_warning(png_ptr, message);
|
||||
|
||||
else
|
||||
png_chunk_benign_error(png_ptr, message);
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
|
||||
else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
|
||||
# endif
|
||||
|
||||
# ifdef PNG_WRITE_SUPPORTED
|
||||
{
|
||||
if (error < PNG_CHUNK_WRITE_ERROR)
|
||||
png_app_warning(png_ptr, message);
|
||||
|
||||
else
|
||||
png_app_error(png_ptr, message);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifdef PNG_ERROR_TEXT_SUPPORTED
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
PNG_FUNCTION(void,
|
||||
png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
|
||||
{
|
||||
# define fixed_message "fixed point overflow in "
|
||||
# define fixed_message_ln ((sizeof fixed_message)-1)
|
||||
unsigned int iin;
|
||||
char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
|
||||
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_structrp png_ptr, png_longjmp_ptr longjmp_fn,
|
||||
size_t jmp_buf_size)
|
||||
{
|
||||
/* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
|
||||
* and it must not change after that. Libpng doesn't care how big the
|
||||
* buffer is, just that it doesn't change.
|
||||
*
|
||||
* If the buffer size is no *larger* than the size of jmp_buf when libpng is
|
||||
* compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
|
||||
* semantics that this call will not fail. If the size is larger, however,
|
||||
* the buffer is allocated and this may fail, causing the function to return
|
||||
* NULL.
|
||||
*/
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (png_ptr->jmp_buf_ptr == NULL)
|
||||
{
|
||||
png_ptr->jmp_buf_size = 0; /* not allocated */
|
||||
|
||||
if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
|
||||
png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
|
||||
|
||||
else
|
||||
{
|
||||
png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
|
||||
png_malloc_warn(png_ptr, jmp_buf_size));
|
||||
|
||||
if (png_ptr->jmp_buf_ptr == NULL)
|
||||
return NULL; /* new NULL return on OOM */
|
||||
|
||||
png_ptr->jmp_buf_size = jmp_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
else /* Already allocated: check the size */
|
||||
{
|
||||
size_t size = png_ptr->jmp_buf_size;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
size = (sizeof png_ptr->jmp_buf_local);
|
||||
if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
|
||||
{
|
||||
/* This is an internal error in libpng: somehow we have been left
|
||||
* with a stack allocated jmp_buf when the application regained
|
||||
* control. It's always possible to fix this up, but for the moment
|
||||
* this is a png_error because that makes it easy to detect.
|
||||
*/
|
||||
png_error(png_ptr, "Libpng jmp_buf still allocated");
|
||||
/* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
|
||||
}
|
||||
}
|
||||
|
||||
if (size != jmp_buf_size)
|
||||
{
|
||||
png_warning(png_ptr, "Application jmp_buf size changed");
|
||||
return NULL; /* caller will probably crash: no choice here */
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally fill in the function, now we have a satisfactory buffer. It is
|
||||
* valid to change the function on every call.
|
||||
*/
|
||||
png_ptr->longjmp_fn = longjmp_fn;
|
||||
return png_ptr->jmp_buf_ptr;
|
||||
}
|
||||
|
||||
void /* PRIVATE */
|
||||
png_free_jmpbuf(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
jmp_buf *jb = png_ptr->jmp_buf_ptr;
|
||||
|
||||
/* A size of 0 is used to indicate a local, stack, allocation of the
|
||||
* pointer; used here and in png.c
|
||||
*/
|
||||
if (jb != NULL && png_ptr->jmp_buf_size > 0)
|
||||
{
|
||||
|
||||
/* This stuff is so that a failure to free the error control structure
|
||||
* does not leave libpng in a state with no valid error handling: the
|
||||
* free always succeeds, if there is an error it gets ignored.
|
||||
*/
|
||||
if (jb != &png_ptr->jmp_buf_local)
|
||||
{
|
||||
/* Make an internal, libpng, jmp_buf to return here */
|
||||
jmp_buf free_jmp_buf;
|
||||
|
||||
if (!setjmp(free_jmp_buf))
|
||||
{
|
||||
png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
|
||||
png_ptr->jmp_buf_size = 0; /* stack allocation */
|
||||
png_ptr->longjmp_fn = longjmp;
|
||||
png_free(png_ptr, jb); /* Return to setjmp on error */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *Always* cancel everything out: */
|
||||
png_ptr->jmp_buf_size = 0;
|
||||
png_ptr->jmp_buf_ptr = NULL;
|
||||
png_ptr->longjmp_fn = 0;
|
||||
}
|
||||
}
|
||||
#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_const_structrp png_ptr, png_const_charp error_message),
|
||||
PNG_NORETURN)
|
||||
{
|
||||
#ifdef PNG_CONSOLE_IO_SUPPORTED
|
||||
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
/* Check on NULL only added in 1.5.4 */
|
||||
if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
|
||||
{
|
||||
/* Strip "#nnnn " from beginning of error message. */
|
||||
int offset;
|
||||
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 ? error_message :
|
||||
"undefined");
|
||||
fprintf(stderr, PNG_STRING_NEWLINE);
|
||||
}
|
||||
#else
|
||||
PNG_UNUSED(error_message) /* Make compiler happy */
|
||||
#endif
|
||||
png_longjmp(png_ptr, 1);
|
||||
}
|
||||
|
||||
PNG_FUNCTION(void,PNGAPI
|
||||
png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
|
||||
{
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
|
||||
png_ptr->jmp_buf_ptr != NULL)
|
||||
png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
|
||||
#else
|
||||
PNG_UNUSED(png_ptr)
|
||||
PNG_UNUSED(val)
|
||||
#endif
|
||||
|
||||
/* If control reaches this point, png_longjmp() must not return. The only
|
||||
* choice is to terminate the whole process (or maybe the thread); to do
|
||||
* this the ANSI-C abort() function is used unless a different method is
|
||||
* implemented by overriding the default configuration setting for
|
||||
* PNG_ABORT().
|
||||
*/
|
||||
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_const_structrp 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 /* WARNINGS */
|
||||
|
||||
/* 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->jmp_buf_ptr, 1)
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_error_fn(png_structrp 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;
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
png_ptr->warning_fn = warning_fn;
|
||||
#else
|
||||
PNG_UNUSED(warning_fn)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* 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_structrp 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_structrp 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
|
||||
|
||||
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
|
||||
defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
|
||||
/* Currently the above both depend on SETJMP_SUPPORTED, however it would be
|
||||
* possible to implement without setjmp support just so long as there is some
|
||||
* way to handle the error return here:
|
||||
*/
|
||||
PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
|
||||
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
|
||||
PNG_NORETURN)
|
||||
{
|
||||
const png_const_structrp png_ptr = png_nonconst_ptr;
|
||||
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
|
||||
|
||||
/* An error is always logged here, overwriting anything (typically a warning)
|
||||
* that is already there:
|
||||
*/
|
||||
if (image != NULL)
|
||||
{
|
||||
png_safecat(image->message, (sizeof image->message), 0, error_message);
|
||||
image->warning_or_error |= PNG_IMAGE_ERROR;
|
||||
|
||||
/* Retrieve the jmp_buf from within the png_control, making this work for
|
||||
* C++ compilation too is pretty tricky: C++ wants a pointer to the first
|
||||
* element of a jmp_buf, but C doesn't tell us the type of that.
|
||||
*/
|
||||
if (image->opaque != NULL && image->opaque->error_buf != NULL)
|
||||
longjmp(png_control_jmp_buf(image->opaque), 1);
|
||||
|
||||
/* Missing longjmp buffer, the following is to help debugging: */
|
||||
{
|
||||
size_t pos = png_safecat(image->message, (sizeof image->message), 0,
|
||||
"bad longjmp: ");
|
||||
png_safecat(image->message, (sizeof image->message), pos,
|
||||
error_message);
|
||||
}
|
||||
}
|
||||
|
||||
/* Here on an internal programming error. */
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
void /* PRIVATE */ PNGCBAPI
|
||||
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
|
||||
{
|
||||
const png_const_structrp png_ptr = png_nonconst_ptr;
|
||||
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
|
||||
|
||||
/* A warning is only logged if there is no prior warning or error. */
|
||||
if (image->warning_or_error == 0)
|
||||
{
|
||||
png_safecat(image->message, (sizeof image->message), 0, warning_message);
|
||||
image->warning_or_error |= PNG_IMAGE_WARNING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int /* PRIVATE */
|
||||
png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
|
||||
{
|
||||
volatile png_imagep image = image_in;
|
||||
volatile int result;
|
||||
volatile png_voidp saved_error_buf;
|
||||
jmp_buf safe_jmpbuf;
|
||||
|
||||
/* Safely execute function(arg) with png_error returning to this function. */
|
||||
saved_error_buf = image->opaque->error_buf;
|
||||
result = setjmp(safe_jmpbuf) == 0;
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
image->opaque->error_buf = safe_jmpbuf;
|
||||
result = function(arg);
|
||||
}
|
||||
|
||||
image->opaque->error_buf = saved_error_buf;
|
||||
|
||||
/* And do the cleanup prior to any failure return. */
|
||||
if (result == 0)
|
||||
png_image_free(image);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
|
||||
#endif /* READ || WRITE */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,267 +0,0 @@
|
|||
|
||||
/* pnginfo.h - header file for PNG reference library
|
||||
*
|
||||
* Last changed in libpng 1.6.1 [March 28, 2013]
|
||||
* Copyright (c) 1998-2002,2004,2006-2013 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
|
||||
*/
|
||||
|
||||
/* 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 are set by png_set_IHDR, called from the application on
|
||||
* write, but the are never actually used by the write code.
|
||||
*/
|
||||
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 */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
/* This is never set during write */
|
||||
png_byte signature[8]; /* magic bytes read by libpng from start of file */
|
||||
#endif
|
||||
|
||||
/* 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_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
/* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
|
||||
* defined. When COLORSPACE is switched on all the colorspace-defining
|
||||
* chunks should be enabled, when GAMMA is switched on all the gamma-defining
|
||||
* chunks should be enabled. If this is not done it becomes possible to read
|
||||
* inconsistent PNG files and assign a probably incorrect interpretation to
|
||||
* the information. (In other words, by carefully choosing which chunks to
|
||||
* recognize the system configuration can select an interpretation for PNG
|
||||
* files containing ambiguous data and this will result in inconsistent
|
||||
* behavior between different libpng builds!)
|
||||
*/
|
||||
png_colorspace colorspace;
|
||||
#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 */
|
||||
#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 /* TEXT */
|
||||
|
||||
#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; /* 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_eXIf_SUPPORTED
|
||||
int num_exif; /* Added at libpng-1.6.31 */
|
||||
png_bytep exif;
|
||||
# ifdef PNG_READ_eXIf_SUPPORTED
|
||||
png_bytep eXIf_buf; /* Added at libpng-1.6.32 */
|
||||
# endif
|
||||
#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_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 */
|
||||
|
||||
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
/* Storage for unknown chunks that the library doesn't recognize. */
|
||||
png_unknown_chunkp unknown_chunks;
|
||||
|
||||
/* The type of this field is limited by the type of
|
||||
* png_struct::user_chunk_cache_max, else overflow can occur.
|
||||
*/
|
||||
int unknown_chunks_num;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_sPLT_SUPPORTED
|
||||
/* Data on sPLT chunks (there may be more than one). */
|
||||
png_sPLT_tp splt_palettes;
|
||||
int splt_palettes_num; /* Match type returned by png_get API */
|
||||
#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 */
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
|
||||
/* pngmem.c - stub functions for memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.6.26 [October 20, 2016]
|
||||
* Copyright (c) 1998-2002,2004,2006-2014,2016 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)
|
||||
/* Free a png_struct */
|
||||
void /* PRIVATE */
|
||||
png_destroy_png_struct(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
/* png_free might call png_error and may certainly call
|
||||
* png_get_mem_ptr, so fake a temporary png_struct to support this.
|
||||
*/
|
||||
png_struct dummy_struct = *png_ptr;
|
||||
memset(png_ptr, 0, (sizeof *png_ptr));
|
||||
png_free(&dummy_struct, png_ptr);
|
||||
|
||||
# ifdef PNG_SETJMP_SUPPORTED
|
||||
/* We may have a jmp_buf left to deallocate. */
|
||||
png_free_jmpbuf(&dummy_struct);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory. For reasonable files, size should never exceed
|
||||
* 64K. However, zlib may allocate more than 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_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
ret = png_malloc(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
memset(ret, 0, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
|
||||
* allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
|
||||
* Checking and error handling must happen outside this routine; it returns NULL
|
||||
* if the allocation cannot be done (for any reason.)
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
/* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
|
||||
* allocators have also been removed in 1.6.0, so any 16-bit system now has
|
||||
* to implement a user memory handler. This checks to be sure it isn't
|
||||
* called with big numbers.
|
||||
*/
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
PNG_UNUSED(png_ptr)
|
||||
#endif
|
||||
|
||||
/* Some compilers complain that this is always true. However, it
|
||||
* can be false when integer overflow happens.
|
||||
*/
|
||||
if (size > 0 && size <= PNG_SIZE_MAX
|
||||
# ifdef PNG_MAX_MALLOC_64K
|
||||
&& size <= 65536U
|
||||
# endif
|
||||
)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
|
||||
return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
|
||||
|
||||
else
|
||||
#endif
|
||||
return malloc((size_t)size); /* checked for truncation above */
|
||||
}
|
||||
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
|
||||
defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
|
||||
/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
|
||||
* that arises because of the checks in png_realloc_array that are repeated in
|
||||
* png_malloc_array.
|
||||
*/
|
||||
static png_voidp
|
||||
png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size)
|
||||
{
|
||||
png_alloc_size_t req = (png_alloc_size_t)nelements; /* known to be > 0 */
|
||||
|
||||
if (req <= PNG_SIZE_MAX/element_size)
|
||||
return png_malloc_base(png_ptr, req * element_size);
|
||||
|
||||
/* The failure case when the request is too large */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_array,(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
if (nelements <= 0 || element_size == 0)
|
||||
png_error(png_ptr, "internal error: array alloc");
|
||||
|
||||
return png_malloc_array_checked(png_ptr, nelements, element_size);
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
|
||||
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
/* These are internal errors: */
|
||||
if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
|
||||
(old_array == NULL && old_elements > 0))
|
||||
png_error(png_ptr, "internal error: array realloc");
|
||||
|
||||
/* Check for overflow on the elements count (so the caller does not have to
|
||||
* check.)
|
||||
*/
|
||||
if (add_elements <= INT_MAX - old_elements)
|
||||
{
|
||||
png_voidp new_array = png_malloc_array_checked(png_ptr,
|
||||
old_elements+add_elements, element_size);
|
||||
|
||||
if (new_array != NULL)
|
||||
{
|
||||
/* Because png_malloc_array worked the size calculations below cannot
|
||||
* overflow.
|
||||
*/
|
||||
if (old_elements > 0)
|
||||
memcpy(new_array, old_array, element_size*(unsigned)old_elements);
|
||||
|
||||
memset((char*)new_array + element_size*(unsigned)old_elements, 0,
|
||||
element_size*(unsigned)add_elements);
|
||||
|
||||
return new_array;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* error */
|
||||
}
|
||||
#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
|
||||
|
||||
/* Various functions that have different error handling are derived from this.
|
||||
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
|
||||
* function png_malloc_default is also provided.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret == NULL)
|
||||
png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED PNG_DEPRECATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Passing 'NULL' here bypasses the application provided memory handler. */
|
||||
ret = png_malloc_base(NULL/*use malloc*/, size);
|
||||
|
||||
if (ret == NULL)
|
||||
png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* USER_MEM */
|
||||
|
||||
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
|
||||
* function will 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_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
png_voidp ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
return ret;
|
||||
|
||||
png_warning(png_ptr, "Out of memory");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
|
||||
* without taking any action.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_free(png_const_structrp 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_constcast(png_structrp,png_ptr), ptr);
|
||||
|
||||
else
|
||||
png_free_default(png_ptr, ptr);
|
||||
}
|
||||
|
||||
PNG_FUNCTION(void,PNGAPI
|
||||
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
#endif /* USER_MEM */
|
||||
|
||||
free(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_structrp 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_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
return png_ptr->mem_ptr;
|
||||
}
|
||||
#endif /* USER_MEM */
|
||||
#endif /* READ || WRITE */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,120 +0,0 @@
|
|||
|
||||
/* pngrio.c - functions for data input
|
||||
*
|
||||
* Last changed in libpng 1.6.24 [August 4, 2016]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 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 than 64K on a 16-bit machine.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_read_data(png_structrp 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.
|
||||
*/
|
||||
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_voidcast(png_FILE_p, png_ptr->io_ptr));
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
#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_structrp 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
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
/* 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");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
png_ptr->output_flush_fn = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* READ */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,483 +0,0 @@
|
|||
|
||||
/* pngstruct.h - header file for PNG reference library
|
||||
*
|
||||
* Last changed in libpng 1.6.32 [August 24, 2017]
|
||||
* Copyright (c) 1998-2002,2004,2006-2017 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 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.
|
||||
*/
|
||||
#ifndef ZLIB_CONST
|
||||
/* We must ensure that zlib uses 'const' in declarations. */
|
||||
# define ZLIB_CONST
|
||||
#endif
|
||||
#include "zlib.h"
|
||||
#ifdef const
|
||||
/* zlib.h sometimes #defines const to nothing, undo this. */
|
||||
# undef const
|
||||
#endif
|
||||
|
||||
/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
|
||||
* with older builds.
|
||||
*/
|
||||
#if ZLIB_VERNUM < 0x1260
|
||||
# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
|
||||
# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
|
||||
#else
|
||||
# define PNGZ_MSG_CAST(s) (s)
|
||||
# define PNGZ_INPUT_CAST(b) (b)
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
/* The type of a compression buffer list used by the write code. */
|
||||
typedef struct png_compression_buffer
|
||||
{
|
||||
struct png_compression_buffer *next;
|
||||
png_byte output[1]; /* actually zbuf_size */
|
||||
} png_compression_buffer, *png_compression_bufferp;
|
||||
|
||||
#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
|
||||
(offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
|
||||
#endif
|
||||
|
||||
/* Colorspace support; structures used in png_struct, png_info and in internal
|
||||
* functions to hold and communicate information about the color space.
|
||||
*
|
||||
* PNG_COLORSPACE_SUPPORTED is only required if the application will perform
|
||||
* colorspace corrections, otherwise all the colorspace information can be
|
||||
* skipped and the size of libpng can be reduced (significantly) by compiling
|
||||
* out the colorspace support.
|
||||
*/
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
/* The chromaticities of the red, green and blue colorants and the chromaticity
|
||||
* of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
|
||||
*/
|
||||
typedef struct png_xy
|
||||
{
|
||||
png_fixed_point redx, redy;
|
||||
png_fixed_point greenx, greeny;
|
||||
png_fixed_point bluex, bluey;
|
||||
png_fixed_point whitex, whitey;
|
||||
} png_xy;
|
||||
|
||||
/* The same data as above but encoded as CIE XYZ values. When this data comes
|
||||
* from chromaticities the sum of the Y values is assumed to be 1.0
|
||||
*/
|
||||
typedef struct png_XYZ
|
||||
{
|
||||
png_fixed_point red_X, red_Y, red_Z;
|
||||
png_fixed_point green_X, green_Y, green_Z;
|
||||
png_fixed_point blue_X, blue_Y, blue_Z;
|
||||
} png_XYZ;
|
||||
#endif /* COLORSPACE */
|
||||
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
/* A colorspace is all the above plus, potentially, profile information;
|
||||
* however at present libpng does not use the profile internally so it is only
|
||||
* stored in the png_info struct (if iCCP is supported.) The rendering intent
|
||||
* is retained here and is checked.
|
||||
*
|
||||
* The file gamma encoding information is also stored here and gamma correction
|
||||
* is done by libpng, whereas color correction must currently be done by the
|
||||
* application.
|
||||
*/
|
||||
typedef struct png_colorspace
|
||||
{
|
||||
#ifdef PNG_GAMMA_SUPPORTED
|
||||
png_fixed_point gamma; /* File gamma */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
png_xy end_points_xy; /* End points as chromaticities */
|
||||
png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
|
||||
png_uint_16 rendering_intent; /* Rendering intent of a profile */
|
||||
#endif
|
||||
|
||||
/* Flags are always defined to simplify the code. */
|
||||
png_uint_16 flags; /* As defined below */
|
||||
} png_colorspace, * PNG_RESTRICT png_colorspacerp;
|
||||
|
||||
typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
|
||||
|
||||
/* General flags for the 'flags' field */
|
||||
#define PNG_COLORSPACE_HAVE_GAMMA 0x0001
|
||||
#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002
|
||||
#define PNG_COLORSPACE_HAVE_INTENT 0x0004
|
||||
#define PNG_COLORSPACE_FROM_gAMA 0x0008
|
||||
#define PNG_COLORSPACE_FROM_cHRM 0x0010
|
||||
#define PNG_COLORSPACE_FROM_sRGB 0x0020
|
||||
#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
|
||||
#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */
|
||||
#define PNG_COLORSPACE_INVALID 0x8000
|
||||
#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags))
|
||||
#endif /* COLORSPACE || GAMMA */
|
||||
|
||||
struct png_struct_def
|
||||
{
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */
|
||||
png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
|
||||
jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
|
||||
size_t jmp_buf_size; /* size of the above, if allocated */
|
||||
#endif
|
||||
png_error_ptr error_fn; /* function for printing errors and aborting */
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
png_error_ptr warning_fn; /* function for printing warnings */
|
||||
#endif
|
||||
png_voidp error_ptr; /* user supplied struct for error functions */
|
||||
png_rw_ptr write_data_fn; /* function for writing output data */
|
||||
png_rw_ptr read_data_fn; /* function for reading input data */
|
||||
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 */
|
||||
|
||||
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
|
||||
z_stream zstream; /* decompression structure */
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
png_compression_bufferp zbuffer_list; /* Created on demand during write */
|
||||
uInt zbuffer_size; /* size of the actual buffer */
|
||||
|
||||
int zlib_level; /* holds zlib compression level */
|
||||
int zlib_method; /* holds zlib compression method */
|
||||
int zlib_window_bits; /* holds zlib compression window bits */
|
||||
int zlib_mem_level; /* holds zlib compression memory level */
|
||||
int zlib_strategy; /* holds zlib compression strategy */
|
||||
#endif
|
||||
/* Added at libpng 1.5.4 */
|
||||
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
|
||||
int zlib_text_level; /* holds zlib compression level */
|
||||
int zlib_text_method; /* holds zlib compression method */
|
||||
int zlib_text_window_bits; /* holds zlib compression window bits */
|
||||
int zlib_text_mem_level; /* holds zlib compression memory level */
|
||||
int zlib_text_strategy; /* holds zlib compression strategy */
|
||||
#endif
|
||||
/* End of material added at libpng 1.5.4 */
|
||||
/* Added at libpng 1.6.0 */
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
int zlib_set_level; /* Actual values set into the zstream on write */
|
||||
int zlib_set_method;
|
||||
int zlib_set_window_bits;
|
||||
int zlib_set_mem_level;
|
||||
int zlib_set_strategy;
|
||||
#endif
|
||||
|
||||
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_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
|
||||
png_bytep prev_row; /* buffer to save previous (unfiltered) row.
|
||||
* While reading this is a pointer into
|
||||
* big_prev_row; while writing it is separately
|
||||
* allocated if needed.
|
||||
*/
|
||||
png_bytep row_buf; /* buffer to save current (unfiltered) row.
|
||||
* While reading, this is a pointer into
|
||||
* big_row_buf; while writing it is separately
|
||||
* allocated.
|
||||
*/
|
||||
#ifdef PNG_WRITE_FILTER_SUPPORTED
|
||||
png_bytep try_row; /* buffer to save trial row when filtering */
|
||||
png_bytep tst_row; /* buffer to save best trial row when filtering */
|
||||
#endif
|
||||
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
|
||||
|
||||
png_uint_32 idat_size; /* current IDAT size for read */
|
||||
png_uint_32 crc; /* current chunk CRC value */
|
||||
png_colorp palette; /* palette from the input file */
|
||||
png_uint_16 num_palette; /* number of color entries in palette */
|
||||
|
||||
/* Added at libpng-1.5.10 */
|
||||
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
int num_palette_max; /* maximum palette index found in IDAT */
|
||||
#endif
|
||||
|
||||
png_uint_16 num_trans; /* number of transparency values */
|
||||
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_ in png.h ) */
|
||||
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: write only */
|
||||
png_byte pixel_depth; /* number of bits per pixel */
|
||||
png_byte channels; /* number of channels in file */
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
png_byte usr_channels; /* channels at start of write: write only */
|
||||
#endif
|
||||
png_byte sig_bytes; /* magic bytes read/written from start of file */
|
||||
png_byte maximum_pixel_depth;
|
||||
/* pixel depth used for the row buffers */
|
||||
png_byte transformed_pixel_depth;
|
||||
/* pixel depth after read/write transforms */
|
||||
#if ZLIB_VERNUM >= 0x1240
|
||||
png_byte zstream_start; /* at start of an input zlib stream */
|
||||
#endif /* Zlib >= 1.2.4 */
|
||||
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
|
||||
png_uint_16 filler; /* filler bytes for pixel expansion */
|
||||
#endif
|
||||
|
||||
#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
|
||||
defined(PNG_READ_ALPHA_MODE_SUPPORTED)
|
||||
png_byte background_gamma_type;
|
||||
png_fixed_point background_gamma;
|
||||
png_color_16 background; /* background color in screen gamma space */
|
||||
#ifdef PNG_READ_GAMMA_SUPPORTED
|
||||
png_color_16 background_1; /* background normalized to gamma 1.0 */
|
||||
#endif
|
||||
#endif /* bKGD */
|
||||
|
||||
#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
|
||||
|
||||
#ifdef PNG_READ_GAMMA_SUPPORTED
|
||||
int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */
|
||||
png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
|
||||
|
||||
png_bytep gamma_table; /* gamma table for 8-bit depth files */
|
||||
png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
|
||||
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
|
||||
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
|
||||
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_from_1; /* converts from 1.0 to screen */
|
||||
png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
|
||||
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
|
||||
#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 */
|
||||
|
||||
#endif /* PROGRESSIVE_READ */
|
||||
|
||||
#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
|
||||
|
||||
/* Options */
|
||||
#ifdef PNG_SET_OPTION_SUPPORTED
|
||||
png_uint_32 options; /* On/off state (up to 16 options) */
|
||||
#endif
|
||||
|
||||
#if PNG_LIBPNG_VER < 10700
|
||||
/* To do: remove this from libpng-1.7 */
|
||||
#ifdef PNG_TIME_RFC1123_SUPPORTED
|
||||
char time_buffer[29]; /* String to hold RFC 1123 time text */
|
||||
#endif
|
||||
#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;
|
||||
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
int unknown_default; /* As PNG_HANDLE_* */
|
||||
unsigned int num_chunk_list; /* Number of entries in the list */
|
||||
png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
|
||||
* followed by a PNG_HANDLE_* byte */
|
||||
#endif
|
||||
|
||||
/* New members added in libpng-1.0.3 */
|
||||
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
png_byte rgb_to_gray_status;
|
||||
/* Added in libpng 1.5.5 to record setting of coefficients: */
|
||||
png_byte rgb_to_gray_coefficients_set;
|
||||
/* 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;
|
||||
/* deleted in 1.5.5: 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)
|
||||
/* 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_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
/* Temporary storage for unknown chunk that the library doesn't recognize,
|
||||
* used while reading the chunk.
|
||||
*/
|
||||
png_unknown_chunk unknown_chunk;
|
||||
#endif
|
||||
|
||||
/* New member added in libpng-1.2.26 */
|
||||
png_size_t old_big_row_buf_size;
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
/* New member added in libpng-1.2.30 */
|
||||
png_bytep read_buffer; /* buffer for reading chunk data */
|
||||
png_alloc_size_t read_buffer_size; /* current size of the buffer */
|
||||
#endif
|
||||
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
uInt IDAT_read_size; /* limit on read buffer size for IDAT */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
/* New member added in libpng-1.4.0 */
|
||||
png_uint_32 io_state;
|
||||
#endif
|
||||
|
||||
/* New member added in libpng-1.5.6 */
|
||||
png_bytep big_prev_row;
|
||||
|
||||
/* New member added in libpng-1.5.7 */
|
||||
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
|
||||
png_bytep row, png_const_bytep prev_row);
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
png_colorspace colorspace;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#endif /* PNGSTRUCT_H */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,864 +0,0 @@
|
|||
|
||||
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
|
||||
*
|
||||
* Last changed in libpng 1.6.33 [September 28, 2017]
|
||||
* Copyright (c) 1998-2002,2004,2006-2017 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_structrp 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_structrp 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_structrp 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;
|
||||
# ifdef PNG_WRITE_SUPPORTED
|
||||
png_ptr->usr_bit_depth = 8;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
/* Turn on packed pixel swapping */
|
||||
void PNGAPI
|
||||
png_set_packswap(png_structrp 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_structrp 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_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_interlace handling");
|
||||
|
||||
if (png_ptr != 0 && png_ptr->interlaced != 0)
|
||||
{
|
||||
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_structrp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
{
|
||||
png_debug(1, "in png_set_filler");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* In libpng 1.6 it is possible to determine whether this is a read or write
|
||||
* operation and therefore to do more checking here for a valid call.
|
||||
*/
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
|
||||
{
|
||||
# ifdef PNG_READ_FILLER_SUPPORTED
|
||||
/* On read png_set_filler is always valid, regardless of the base PNG
|
||||
* format, because other transformations can give a format where the
|
||||
* filler code can execute (basically an 8 or 16-bit component RGB or G
|
||||
* format.)
|
||||
*
|
||||
* NOTE: usr_channels is not used by the read code! (This has led to
|
||||
* confusion in the past.) The filler is only used in the read code.
|
||||
*/
|
||||
png_ptr->filler = (png_uint_16)filler;
|
||||
# else
|
||||
png_app_error(png_ptr, "png_set_filler not supported on read");
|
||||
PNG_UNUSED(filler) /* not used in the write case */
|
||||
return;
|
||||
# endif
|
||||
}
|
||||
|
||||
else /* write */
|
||||
{
|
||||
# ifdef PNG_WRITE_FILLER_SUPPORTED
|
||||
/* On write the usr_channels parameter must be set correctly at the
|
||||
* start to record the number of channels in the app-supplied data.
|
||||
*/
|
||||
switch (png_ptr->color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
png_ptr->usr_channels = 4;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
if (png_ptr->bit_depth >= 8)
|
||||
{
|
||||
png_ptr->usr_channels = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* There simply isn't any code in libpng to strip out bits
|
||||
* from bytes when the components are less than a byte in
|
||||
* size!
|
||||
*/
|
||||
png_app_error(png_ptr,
|
||||
"png_set_filler is invalid for"
|
||||
" low bit depth gray output");
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
png_app_error(png_ptr,
|
||||
"png_set_filler: inappropriate color type");
|
||||
return;
|
||||
}
|
||||
# else
|
||||
png_app_error(png_ptr, "png_set_filler not supported on write");
|
||||
return;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Here on success - libpng supports the operation, set the transformation
|
||||
* and the flag to say where the filler channel is.
|
||||
*/
|
||||
png_ptr->transformations |= PNG_FILLER;
|
||||
|
||||
if (filler_loc == PNG_FILLER_AFTER)
|
||||
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
|
||||
|
||||
else
|
||||
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
|
||||
}
|
||||
|
||||
/* Added to libpng-1.2.7 */
|
||||
void PNGAPI
|
||||
png_set_add_alpha(png_structrp 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);
|
||||
/* The above may fail to do anything. */
|
||||
if ((png_ptr->transformations & PNG_FILLER) != 0)
|
||||
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_structrp 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_structrp 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_structrp 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)
|
||||
{
|
||||
#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
|
||||
/* Feature added to libpng-1.6.11 for testing purposes, not
|
||||
* enabled by default.
|
||||
*/
|
||||
*(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
|
||||
#else
|
||||
png_byte t = *rp;
|
||||
*rp = *(rp + 1);
|
||||
*(rp + 1) = t;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#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 /* PACKSWAP || WRITE_PACKSWAP */
|
||||
|
||||
#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.
|
||||
*
|
||||
* at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
|
||||
* nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
|
||||
*/
|
||||
|
||||
/* GA, GX, XG cases */
|
||||
if (row_info->channels == 2)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
if (at_start != 0) /* Skip initial filler */
|
||||
++sp;
|
||||
else /* Skip initial channel 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 != 0) /* Skip initial filler */
|
||||
sp += 2;
|
||||
else /* Skip initial channel and, for sp, the filler */
|
||||
{
|
||||
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 != 0) /* 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 != 0) /* Skip initial filler */
|
||||
sp += 2;
|
||||
else /* Skip initial channels and, for sp, the filler */
|
||||
{
|
||||
sp += 8; dp += 6;
|
||||
}
|
||||
|
||||
while (sp < ep)
|
||||
{
|
||||
/* Copy 6 bytes, skip 2 */
|
||||
*dp++ = *sp++; *dp++ = *sp++;
|
||||
*dp++ = *sp++; *dp++ = *sp++;
|
||||
*dp++ = *sp++; *dp++ = *sp; sp += 3;
|
||||
}
|
||||
|
||||
row_info->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 = (png_size_t)(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) != 0)
|
||||
{
|
||||
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 /* READ_BGR || WRITE_BGR */
|
||||
|
||||
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
|
||||
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
|
||||
/* Added at libpng-1.5.10 */
|
||||
void /* PRIVATE */
|
||||
png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
|
||||
png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
|
||||
{
|
||||
/* Calculations moved outside switch in an attempt to stop different
|
||||
* compiler warnings. 'padding' is in *bits* within the last byte, it is
|
||||
* an 'int' because pixel_depth becomes an 'int' in the expression below,
|
||||
* and this calculation is used because it avoids warnings that other
|
||||
* forms produced on either GCC or MSVC.
|
||||
*/
|
||||
int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
|
||||
png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
|
||||
|
||||
switch (row_info->bit_depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
/* in this case, all bytes must be 0 so we don't need
|
||||
* to unpack the pixels except for the rightmost one.
|
||||
*/
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
if ((*rp >> padding) != 0)
|
||||
png_ptr->num_palette_max = 1;
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
int i = ((*rp >> padding) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 2) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 4) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 6) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
int i = ((*rp >> padding) & 0x0f);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 4) & 0x0f);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
if (*rp > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = (int) *rp;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CHECK_FOR_INVALID_INDEX */
|
||||
|
||||
#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_structrp 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;
|
||||
|
||||
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
|
||||
(png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
|
||||
{
|
||||
png_app_error(png_ptr,
|
||||
"info change after png_start_read_image or png_read_update_info");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
return png_ptr->user_transform_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_current_row_number(png_const_structrp png_ptr)
|
||||
{
|
||||
/* See the comments in png.h - this is the sub-image row when reading an
|
||||
* 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_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
return png_ptr->pass;
|
||||
return 8; /* invalid */
|
||||
}
|
||||
#endif /* USER_TRANSFORM_INFO */
|
||||
#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
|
||||
#endif /* READ || WRITE */
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# pngusr.dfa
|
||||
#
|
||||
# Build time configuration of libpng
|
||||
#
|
||||
# Enter build configuration options in this file
|
||||
#
|
||||
# Security settings: by default these limits are unset, you can change them
|
||||
# here by entering the appropriate values as #defines preceded by '@' (to cause,
|
||||
# them to be passed through to the build of pnglibconf.h), for example:
|
||||
#
|
||||
# @# define PNG_USER_WIDTH_MAX 65535
|
||||
# @# define PNG_USER_HEIGHT_MAX 65535
|
||||
# @# define PNG_USER_CHUNK_CACHE_MAX 256
|
||||
# @# define PNG_USER_CHUNK_MALLOC_MAX 640000
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
|
||||
/* pngwio.c - functions for data output
|
||||
*
|
||||
* Last changed in libpng 1.6.24 [August 4, 2016]
|
||||
* Copyright (c) 1998-2002,2004,2006-2014,2016 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_structrp 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_constcast(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.
|
||||
*/
|
||||
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");
|
||||
}
|
||||
#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_structrp 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_voidcast(png_FILE_p, (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_structrp 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
|
||||
#else
|
||||
PNG_UNUSED(output_flush_fn)
|
||||
#endif /* WRITE_FLUSH */
|
||||
|
||||
#ifdef PNG_READ_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");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* WRITE */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,576 +0,0 @@
|
|||
|
||||
/* pngwtran.c - transforms the data in a row for PNG writers
|
||||
*
|
||||
* Last changed in libpng 1.6.26 [October 20, 2016]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 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_TRANSFORMS_SUPPORTED
|
||||
|
||||
#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).
|
||||
*/
|
||||
static void
|
||||
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;
|
||||
unsigned int shift;
|
||||
int 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;
|
||||
unsigned int shift;
|
||||
int 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.
|
||||
*/
|
||||
static void
|
||||
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];
|
||||
unsigned int channels = 0;
|
||||
|
||||
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
|
||||
{
|
||||
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) != 0)
|
||||
{
|
||||
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;
|
||||
unsigned int 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++)
|
||||
{
|
||||
int j;
|
||||
unsigned int v, out;
|
||||
|
||||
v = *bp;
|
||||
out = 0;
|
||||
|
||||
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
|
||||
{
|
||||
if (j > 0)
|
||||
out |= v << j;
|
||||
|
||||
else
|
||||
out |= (v >> (-j)) & mask;
|
||||
}
|
||||
|
||||
*bp = (png_byte)(out & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
|
||||
const unsigned int c = i%channels;
|
||||
int j;
|
||||
unsigned int v, out;
|
||||
|
||||
v = *bp;
|
||||
out = 0;
|
||||
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
out |= v << j;
|
||||
|
||||
else
|
||||
out |= v >> (-j);
|
||||
}
|
||||
|
||||
*bp = (png_byte)(out & 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++)
|
||||
{
|
||||
const unsigned int c = i%channels;
|
||||
int j;
|
||||
unsigned int value, v;
|
||||
|
||||
v = png_get_uint_16(bp);
|
||||
value = 0;
|
||||
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
value |= v << j;
|
||||
|
||||
else
|
||||
value |= v >> (-j);
|
||||
}
|
||||
*bp++ = (png_byte)((value >> 8) & 0xff);
|
||||
*bp++ = (png_byte)(value & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
static void
|
||||
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 /* WRITE_16BIT */
|
||||
}
|
||||
|
||||
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 /* WRITE_16BIT */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
static void
|
||||
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 /* WRITE_16BIT */
|
||||
}
|
||||
|
||||
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 /* WRITE_16BIT */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Transform the data according to the user's wishes. The order of
|
||||
* transformations is significant.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
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) != 0)
|
||||
if (png_ptr->write_user_transform_fn != NULL)
|
||||
(*(png_ptr->write_user_transform_fn)) /* User write transform
|
||||
function */
|
||||
(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) != 0)
|
||||
png_do_strip_channel(row_info, png_ptr->row_buf + 1,
|
||||
!(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
|
||||
png_do_packswap(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_PACK_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_PACK) != 0)
|
||||
png_do_pack(row_info, png_ptr->row_buf + 1,
|
||||
(png_uint_32)png_ptr->bit_depth);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SWAP_SUPPORTED
|
||||
# ifdef PNG_16BIT_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
|
||||
png_do_swap(row_info, png_ptr->row_buf + 1);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SHIFT_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_SHIFT) != 0)
|
||||
png_do_shift(row_info, png_ptr->row_buf + 1,
|
||||
&(png_ptr->shift));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
|
||||
png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
|
||||
png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_BGR_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_BGR) != 0)
|
||||
png_do_bgr(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_INVERT_SUPPORTED
|
||||
if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
|
||||
png_do_invert(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
}
|
||||
#endif /* WRITE_TRANSFORMS */
|
||||
#endif /* WRITE */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,767 +0,0 @@
|
|||
/* filter_vsx_intrinsics.c - PowerPC optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2017 Glenn Randers-Pehrson
|
||||
* Written by Vadim Barkov, 2017.
|
||||
* Last changed in libpng 1.6.29 [March 16, 2017]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* This code requires -maltivec and -mvsx on the command line: */
|
||||
#if PNG_POWERPC_VSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||
|
||||
#include <altivec.h>
|
||||
|
||||
#if PNG_POWERPC_VSX_OPT > 0
|
||||
|
||||
#ifndef __VSX__
|
||||
# error "This code requires VSX support (POWER7 and later). Please provide -mvsx compiler flag."
|
||||
#endif
|
||||
|
||||
#define vec_ld_unaligned(vec,data) vec = vec_vsx_ld(0,data)
|
||||
#define vec_st_unaligned(vec,data) vec_vsx_st(vec,0,data)
|
||||
|
||||
|
||||
/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
|
||||
* They're positioned like this:
|
||||
* prev: c b
|
||||
* row: a d
|
||||
* The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
|
||||
* whichever of a, b, or c is closest to p=a+b-c.
|
||||
* ( this is taken from ../intel/filter_sse2_intrinsics.c )
|
||||
*/
|
||||
|
||||
#define vsx_declare_common_vars(row_info,row,prev_row,offset) \
|
||||
png_byte i;\
|
||||
png_bytep rp = row + offset;\
|
||||
png_const_bytep pp = prev_row;\
|
||||
png_size_t unaligned_top = 16 - (((png_size_t)rp % 16));\
|
||||
png_size_t istop;\
|
||||
if(unaligned_top == 16)\
|
||||
unaligned_top = 0;\
|
||||
istop = row_info->rowbytes;\
|
||||
if((unaligned_top < istop))\
|
||||
istop -= unaligned_top;\
|
||||
else{\
|
||||
unaligned_top = istop;\
|
||||
istop = 0;\
|
||||
}
|
||||
|
||||
void png_read_filter_row_up_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char pp_vec;
|
||||
vsx_declare_common_vars(row_info,row,prev_row,0)
|
||||
|
||||
/* Altivec operations require 16-byte aligned data
|
||||
* but input can be unaligned. So we calculate
|
||||
* unaligned part as usual.
|
||||
*/
|
||||
for (i = 0; i < unaligned_top; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Using SIMD while we can */
|
||||
while( istop >= 16 )
|
||||
{
|
||||
rp_vec = vec_ld(0,rp);
|
||||
vec_ld_unaligned(pp_vec,pp);
|
||||
|
||||
rp_vec = vec_add(rp_vec,pp_vec);
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
pp += 16;
|
||||
rp += 16;
|
||||
istop -= 16;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
{
|
||||
/* If byte count of row is not divisible by 16
|
||||
* we will process remaining part as usual
|
||||
*/
|
||||
for (i = 0; i < istop; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const vector unsigned char VSX_LEFTSHIFTED1_4 = {16,16,16,16, 0, 1, 2, 3,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_LEFTSHIFTED2_4 = {16,16,16,16,16,16,16,16, 4, 5, 6, 7,16,16,16,16};
|
||||
static const vector unsigned char VSX_LEFTSHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 8, 9,10,11};
|
||||
|
||||
static const vector unsigned char VSX_LEFTSHIFTED1_3 = {16,16,16, 0, 1, 2,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_LEFTSHIFTED2_3 = {16,16,16,16,16,16, 3, 4, 5,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_LEFTSHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 6, 7, 8,16,16,16,16};
|
||||
static const vector unsigned char VSX_LEFTSHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 9,10,11,16};
|
||||
|
||||
static const vector unsigned char VSX_NOT_SHIFTED1_4 = {16,16,16,16, 4, 5, 6, 7,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_NOT_SHIFTED2_4 = {16,16,16,16,16,16,16,16, 8, 9,10,11,16,16,16,16};
|
||||
static const vector unsigned char VSX_NOT_SHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,15};
|
||||
|
||||
static const vector unsigned char VSX_NOT_SHIFTED1_3 = {16,16,16, 3, 4, 5,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_NOT_SHIFTED2_3 = {16,16,16,16,16,16, 6, 7, 8,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_NOT_SHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 9,10,11,16,16,16,16};
|
||||
static const vector unsigned char VSX_NOT_SHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,16};
|
||||
|
||||
static const vector unsigned char VSX_CHAR_ZERO = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = { 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = { 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {12,16,13,16,14,16,15,16,16,16,16,16,16,16,16,16};
|
||||
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 0, 2, 4, 6,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 0, 2, 4, 6,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4, 6};
|
||||
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = { 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = { 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = { 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {12,16,13,16,14,16,16,16,16,16,16,16,16,16,16,16};
|
||||
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 0, 2, 4,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 0, 2, 4,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 0, 2, 4,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4,16};
|
||||
|
||||
#elif defined(__BIG_ENDIAN__)
|
||||
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = {16, 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = {16, 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {16,12,16,13,16,14,16,15,16,16,16,16,16,16,16,16};
|
||||
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 1, 3, 5, 7,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 1, 3, 5, 7,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5, 7};
|
||||
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = {16, 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = {16, 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = {16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {16,12,16,13,16,14,16,16,16,16,16,16,16,16,16,16};
|
||||
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 1, 3, 5,16,16,16,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 1, 3, 5,16,16,16,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 1, 3, 5,16,16,16,16};
|
||||
static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5,16};
|
||||
|
||||
#endif
|
||||
|
||||
#define vsx_char_to_short(vec,offset,bpp) (vector unsigned short)vec_perm((vec),VSX_CHAR_ZERO,VSX_CHAR_TO_SHORT##offset##_##bpp)
|
||||
#define vsx_short_to_char(vec,offset,bpp) vec_perm(((vector unsigned char)(vec)),VSX_CHAR_ZERO,VSX_SHORT_TO_CHAR##offset##_##bpp)
|
||||
|
||||
#ifdef PNG_USE_ABS
|
||||
# define vsx_abs(number) abs(number)
|
||||
#else
|
||||
# define vsx_abs(number) (number > 0) ? (number) : -(number)
|
||||
#endif
|
||||
|
||||
void png_read_filter_row_sub4_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 4;
|
||||
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char part_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
|
||||
PNG_UNUSED(pp)
|
||||
|
||||
/* Altivec operations require 16-byte aligned data
|
||||
* but input can be unaligned. So we calculate
|
||||
* unaligned part as usual.
|
||||
*/
|
||||
for (i = 0; i < unaligned_top; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Using SIMD while we can */
|
||||
while( istop >= 16 )
|
||||
{
|
||||
for(i=0;i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
rp -= bpp;
|
||||
|
||||
rp_vec = vec_ld(0,rp);
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
rp += 16;
|
||||
istop -= 16;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp - bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void png_read_filter_row_sub3_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 3;
|
||||
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char part_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
|
||||
PNG_UNUSED(pp)
|
||||
|
||||
/* Altivec operations require 16-byte aligned data
|
||||
* but input can be unaligned. So we calculate
|
||||
* unaligned part as usual.
|
||||
*/
|
||||
for (i = 0; i < unaligned_top; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Using SIMD while we can */
|
||||
while( istop >= 16 )
|
||||
{
|
||||
for(i=0;i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
rp -= bpp;
|
||||
|
||||
rp_vec = vec_ld(0,rp);
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3);
|
||||
rp_vec = vec_add(rp_vec,part_vec);
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
rp += 15;
|
||||
istop -= 16;
|
||||
|
||||
/* Since 16 % bpp = 16 % 3 = 1, last element of array must
|
||||
* be proceeded manually
|
||||
*/
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg4_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 4;
|
||||
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char pp_vec;
|
||||
vector unsigned char pp_part_vec;
|
||||
vector unsigned char rp_part_vec;
|
||||
vector unsigned char avg_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
rp -= bpp;
|
||||
if(istop >= bpp)
|
||||
istop -= bpp;
|
||||
|
||||
for (i = 0; i < bpp; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
((int)(*pp++) / 2 )) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Altivec operations require 16-byte aligned data
|
||||
* but input can be unaligned. So we calculate
|
||||
* unaligned part as usual.
|
||||
*/
|
||||
for (i = 0; i < unaligned_top; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Using SIMD while we can */
|
||||
while( istop >= 16 )
|
||||
{
|
||||
for(i=0;i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
rp -= bpp;
|
||||
pp -= bpp;
|
||||
|
||||
vec_ld_unaligned(pp_vec,pp);
|
||||
rp_vec = vec_ld(0,rp);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_4);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_4);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_4);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
rp += 16;
|
||||
pp += 16;
|
||||
istop -= 16;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_avg3_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 3;
|
||||
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char pp_vec;
|
||||
vector unsigned char pp_part_vec;
|
||||
vector unsigned char rp_part_vec;
|
||||
vector unsigned char avg_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
rp -= bpp;
|
||||
if(istop >= bpp)
|
||||
istop -= bpp;
|
||||
|
||||
for (i = 0; i < bpp; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
((int)(*pp++) / 2 )) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Altivec operations require 16-byte aligned data
|
||||
* but input can be unaligned. So we calculate
|
||||
* unaligned part as usual.
|
||||
*/
|
||||
for (i = 0; i < unaligned_top; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
|
||||
/* Using SIMD while we can */
|
||||
while( istop >= 16 )
|
||||
{
|
||||
for(i=0;i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
rp -= bpp;
|
||||
pp -= bpp;
|
||||
|
||||
vec_ld_unaligned(pp_vec,pp);
|
||||
rp_vec = vec_ld(0,rp);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_3);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_3);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_3);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3);
|
||||
pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED4_3);
|
||||
avg_vec = vec_avg(rp_part_vec,pp_part_vec);
|
||||
avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
|
||||
rp_vec = vec_add(rp_vec,avg_vec);
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
rp += 15;
|
||||
pp += 15;
|
||||
istop -= 16;
|
||||
|
||||
/* Since 16 % bpp = 16 % 3 = 1, last element of array must
|
||||
* be proceeded manually
|
||||
*/
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
rp++;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
*rp = (png_byte)(((int)(*rp) +
|
||||
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bytewise c ? t : e. */
|
||||
#define if_then_else(c,t,e) vec_sel(e,t,c)
|
||||
|
||||
#define vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) {\
|
||||
c = *(pp - bpp);\
|
||||
a = *(rp - bpp);\
|
||||
b = *pp++;\
|
||||
p = b - c;\
|
||||
pc = a - c;\
|
||||
pa = vsx_abs(p);\
|
||||
pb = vsx_abs(pc);\
|
||||
pc = vsx_abs(p + pc);\
|
||||
if (pb < pa) pa = pb, a = b;\
|
||||
if (pc < pa) a = c;\
|
||||
a += *rp;\
|
||||
*rp++ = (png_byte)a;\
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth4_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 4;
|
||||
|
||||
int a, b, c, pa, pb, pc, p;
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char pp_vec;
|
||||
vector unsigned short a_vec,b_vec,c_vec,nearest_vec;
|
||||
vector signed short pa_vec,pb_vec,pc_vec,smallest_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
rp -= bpp;
|
||||
if(istop >= bpp)
|
||||
istop -= bpp;
|
||||
|
||||
/* Process the first pixel in the row completely (this is the same as 'up'
|
||||
* because there is only one candidate predictor for the first row).
|
||||
*/
|
||||
for(i = 0; i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)( *rp + *pp);
|
||||
rp++;
|
||||
pp++;
|
||||
}
|
||||
|
||||
for(i = 0; i < unaligned_top ; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
|
||||
while( istop >= 16)
|
||||
{
|
||||
for(i = 0; i < bpp ; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
|
||||
rp -= bpp;
|
||||
pp -= bpp;
|
||||
rp_vec = vec_ld(0,rp);
|
||||
vec_ld_unaligned(pp_vec,pp);
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_4),1,4);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,4)));
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_4),2,4);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,4)));
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_4),3,4);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,4)));
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
rp += 16;
|
||||
pp += 16;
|
||||
istop -= 16;
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
}
|
||||
|
||||
void png_read_filter_row_paeth3_vsx(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
const png_byte bpp = 3;
|
||||
|
||||
int a, b, c, pa, pb, pc, p;
|
||||
vector unsigned char rp_vec;
|
||||
vector unsigned char pp_vec;
|
||||
vector unsigned short a_vec,b_vec,c_vec,nearest_vec;
|
||||
vector signed short pa_vec,pb_vec,pc_vec,smallest_vec;
|
||||
|
||||
vsx_declare_common_vars(row_info,row,prev_row,bpp)
|
||||
rp -= bpp;
|
||||
if(istop >= bpp)
|
||||
istop -= bpp;
|
||||
|
||||
/* Process the first pixel in the row completely (this is the same as 'up'
|
||||
* because there is only one candidate predictor for the first row).
|
||||
*/
|
||||
for(i = 0; i < bpp ; i++)
|
||||
{
|
||||
*rp = (png_byte)( *rp + *pp);
|
||||
rp++;
|
||||
pp++;
|
||||
}
|
||||
|
||||
for(i = 0; i < unaligned_top ; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
|
||||
while( istop >= 16)
|
||||
{
|
||||
for(i = 0; i < bpp ; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
|
||||
rp -= bpp;
|
||||
pp -= bpp;
|
||||
rp_vec = vec_ld(0,rp);
|
||||
vec_ld_unaligned(pp_vec,pp);
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_3),1,3);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,3)));
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_3),2,3);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,3)));
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_3),3,3);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,3)));
|
||||
|
||||
a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3);
|
||||
b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED4_3),4,3);
|
||||
c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3);
|
||||
pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
|
||||
pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
|
||||
pc_vec = vec_add(pa_vec,pb_vec);
|
||||
pa_vec = vec_abs(pa_vec);
|
||||
pb_vec = vec_abs(pb_vec);
|
||||
pc_vec = vec_abs(pc_vec);
|
||||
smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
|
||||
nearest_vec = if_then_else(
|
||||
vec_cmpeq(pa_vec,smallest_vec),
|
||||
a_vec,
|
||||
if_then_else(
|
||||
vec_cmpeq(pb_vec,smallest_vec),
|
||||
b_vec,
|
||||
c_vec
|
||||
)
|
||||
);
|
||||
rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,4,3)));
|
||||
|
||||
vec_st(rp_vec,0,rp);
|
||||
|
||||
rp += 15;
|
||||
pp += 15;
|
||||
istop -= 16;
|
||||
|
||||
/* Since 16 % bpp = 16 % 3 = 1, last element of array must
|
||||
* be proceeded manually
|
||||
*/
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
|
||||
if(istop > 0)
|
||||
for (i = 0; i < istop % 16; i++)
|
||||
{
|
||||
vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PNG_POWERPC_VSX_OPT > 0 */
|
||||
#endif /* PNG_POWERPC_VSX_IMPLEMENTATION == 1 (intrinsics) */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
|
||||
/* powerpc_init.c - POWERPC optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2017 Glenn Randers-Pehrson
|
||||
* Written by Vadim Barkov, 2017.
|
||||
* Last changed in libpng 1.6.29 [March 16, 2017]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
|
||||
* called.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
#if PNG_POWERPC_VSX_OPT > 0
|
||||
#ifdef PNG_POWERPC_VSX_CHECK_SUPPORTED /* Do run-time checks */
|
||||
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||
* run-time checks for CPU features if at all possible. In the case of the PowerPC
|
||||
* VSX instructions there is no processor-specific way of detecting the
|
||||
* presence of the required support, therefore run-time detection is extremely
|
||||
* OS specific.
|
||||
*
|
||||
* You may set the macro PNG_POWERPC_VSX_FILE to the file name of file containing
|
||||
* a fragment of C source code which defines the png_have_vsx function. There
|
||||
* are a number of implementations in contrib/powerpc-vsx, but the only one that
|
||||
* has partial support is contrib/powerpc-vsx/linux.c - a generic Linux
|
||||
* implementation which reads /proc/cpufino.
|
||||
*/
|
||||
#ifndef PNG_POWERPC_VSX_FILE
|
||||
# ifdef __linux__
|
||||
# define PNG_POWERPC_VSX_FILE "contrib/powerpc-vsx/linux_aux.c"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_POWERPC_VSX_FILE
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
static int png_have_vsx(png_structp png_ptr);
|
||||
#include PNG_POWERPC_VSX_FILE
|
||||
|
||||
#else /* PNG_POWERPC_VSX_FILE */
|
||||
# error "PNG_POWERPC_VSX_FILE undefined: no support for run-time POWERPC VSX checks"
|
||||
#endif /* PNG_POWERPC_VSX_FILE */
|
||||
#endif /* PNG_POWERPC_VSX_CHECK_SUPPORTED */
|
||||
|
||||
void
|
||||
png_init_filter_functions_vsx(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The switch statement is compiled in for POWERPC_VSX_API, the call to
|
||||
* png_have_vsx is compiled in for POWERPC_VSX_CHECK. If both are defined
|
||||
* the check is only performed if the API has not set the PowerPC option on
|
||||
* or off explicitly. In this case the check controls what happens.
|
||||
*/
|
||||
|
||||
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
|
||||
switch ((pp->options >> PNG_POWERPC_VSX) & 3)
|
||||
{
|
||||
case PNG_OPTION_UNSET:
|
||||
/* Allow the run-time check to execute if it has been enabled -
|
||||
* thus both API and CHECK can be turned on. If it isn't supported
|
||||
* this case will fall through to the 'default' below, which just
|
||||
* returns.
|
||||
*/
|
||||
#endif /* PNG_POWERPC_VSX_API_SUPPORTED */
|
||||
#ifdef PNG_POWERPC_VSX_CHECK_SUPPORTED
|
||||
{
|
||||
static volatile sig_atomic_t no_vsx = -1; /* not checked */
|
||||
|
||||
if (no_vsx < 0)
|
||||
no_vsx = !png_have_vsx(pp);
|
||||
|
||||
if (no_vsx)
|
||||
return;
|
||||
}
|
||||
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
|
||||
break;
|
||||
#endif
|
||||
#endif /* PNG_POWERPC_VSX_CHECK_SUPPORTED */
|
||||
|
||||
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
|
||||
default: /* OFF or INVALID */
|
||||
return;
|
||||
|
||||
case PNG_OPTION_ON:
|
||||
/* Option turned on */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IMPORTANT: any new internal functions used here must be declared using
|
||||
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||
* 'prefix' option to configure works:
|
||||
*
|
||||
* ./configure --with-libpng-prefix=foobar_
|
||||
*
|
||||
* Verify you have got this right by running the above command, doing a build
|
||||
* and examining pngprefix.h; it must contain a #define for every external
|
||||
* function you add. (Notice that this happens automatically for the
|
||||
* initialization function.)
|
||||
*/
|
||||
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_vsx;
|
||||
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_vsx;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_vsx;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_vsx;
|
||||
}
|
||||
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_vsx;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_vsx;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_vsx;
|
||||
}
|
||||
}
|
||||
#endif /* PNG_POWERPC_VSX_OPT > 0 */
|
||||
#endif /* READ */
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
#!/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',
|
||||
# the value of the awk variable "of" (which can be changed on the
|
||||
# command line if required.) 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
|
||||
of="symbols.new" # default to a fixed name
|
||||
}
|
||||
|
||||
# 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
|
||||
# Add a standard header to symbols.new:
|
||||
print ";Version INSERT-VERSION-HERE" >of
|
||||
print ";--------------------------------------------------------------" >of
|
||||
print "; LIBPNG symbol list as a Win32 DEF file" >of
|
||||
print "; Contains all the symbols that can be exported from libpng" >of
|
||||
print ";--------------------------------------------------------------" >of
|
||||
print "LIBRARY" >of
|
||||
print "" >of
|
||||
print "EXPORTS" >of
|
||||
|
||||
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 > of
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
print "*** A new list is in", of, "***"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/* def.c - define format of libpng.def
|
||||
*
|
||||
* Last changed in libpng version 1.6.16 [December 22, 2014]
|
||||
* Copyright (c) 2011-2014 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
|
||||
*/
|
||||
|
||||
/* Write the export file header: */
|
||||
PNG_DFN ";--------------------------------------------------------------"
|
||||
PNG_DFN "; LIBPNG module definition file for OS/2"
|
||||
PNG_DFN ";--------------------------------------------------------------"
|
||||
PNG_DFN ""
|
||||
PNG_DFN "; If you give the library an explicit name one or other files"
|
||||
PNG_DFN "; may need modifying to support the new name on one or more"
|
||||
PNG_DFN "; systems."
|
||||
PNG_DFN "LIBRARY"
|
||||
PNG_DFN "OS2 DESCRIPTION "PNG image compression library""
|
||||
PNG_DFN "OS2 CODE PRELOAD MOVEABLE DISCARDABLE"
|
||||
PNG_DFN ""
|
||||
PNG_DFN "EXPORTS"
|
||||
PNG_DFN ";Version 1.6.35beta02"
|
||||
|
||||
#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
|
||||
PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
|
||||
|
||||
#include "../png.h"
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
#!/bin/awk -f
|
||||
# scripts/dfn.awk - process a .dfn file
|
||||
#
|
||||
# last changed in libpng version 1.5.19 - August 21, 2014
|
||||
#
|
||||
# Copyright (c) 2013-2014 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', which should be set on the command line.
|
||||
# Error messages are printed to stdout and if any are printed
|
||||
# the script will exit with error code 1.
|
||||
|
||||
BEGIN{
|
||||
out="/dev/null" # as a flag
|
||||
out_count=0 # count of output lines
|
||||
err=0 # set if an error occurred
|
||||
sort=0 # sort the output
|
||||
array[""]=""
|
||||
}
|
||||
|
||||
# The output file must be specified before any input:
|
||||
NR==1 && out == "/dev/null" {
|
||||
print "out=output.file must be given on the command line"
|
||||
# but continue without setting the error code; this allows the
|
||||
# script to be checked easily
|
||||
}
|
||||
|
||||
# Output can be sorted; two lines are recognized
|
||||
$1 == "PNG_DFN_START_SORT"{
|
||||
sort=0+$2
|
||||
next
|
||||
}
|
||||
|
||||
$1 ~ /^PNG_DFN_END_SORT/{
|
||||
# Do a very simple, slow, sort; notice that blank lines won't be
|
||||
# output by this
|
||||
for (entry in array) {
|
||||
while (array[entry] != "") {
|
||||
key = entry
|
||||
value = array[key]
|
||||
array[key] = ""
|
||||
|
||||
for (alt in array) {
|
||||
if (array[alt] != "" && alt < key) {
|
||||
array[key] = value
|
||||
value = array[alt]
|
||||
key = alt
|
||||
array[alt] = ""
|
||||
}
|
||||
}
|
||||
|
||||
print value >out
|
||||
}
|
||||
}
|
||||
sort=0
|
||||
next
|
||||
}
|
||||
|
||||
/^[^"]*PNG_DFN *".*"[^"]*$/{
|
||||
# A definition line, apparently correctly formatted; extract the
|
||||
# definition then replace any doubled "" that remain with a single
|
||||
# double quote. Notice that the original doubled double quotes
|
||||
# may have been split by tokenization
|
||||
#
|
||||
# Sometimes GCC splits the PNG_DFN lines; we know this has happened
|
||||
# if the quotes aren't closed and must read another line. In this
|
||||
# case it is essential to reject lines that start with '#' because those
|
||||
# are introduced #line directives.
|
||||
orig=$0
|
||||
line=$0
|
||||
lineno=FNR
|
||||
if (lineno == "") lineno=NR
|
||||
|
||||
if (sub(/^[^"]*PNG_DFN *"/,"",line) != 1) {
|
||||
print "line", lineno ": processing failed:"
|
||||
print orig
|
||||
err=1
|
||||
next
|
||||
} else {
|
||||
++out_count
|
||||
}
|
||||
|
||||
# Now examine quotes within the value:
|
||||
#
|
||||
# @" - delete this and any following spaces
|
||||
# "@ - delete this and any preceding spaces
|
||||
# @' - replace this by a double quote
|
||||
#
|
||||
# This allows macro substitution by the C compiler thus:
|
||||
#
|
||||
# #define first_name John
|
||||
# #define last_name Smith
|
||||
#
|
||||
# PNG_DFN"#define name @'@" first_name "@ @" last_name "@@'"
|
||||
#
|
||||
# Might get C preprocessed to:
|
||||
#
|
||||
# PNG_DFN "#define foo @'@" John "@ @" Smith "@@'"
|
||||
#
|
||||
# Which this script reduces to:
|
||||
#
|
||||
# #define name "John Smith"
|
||||
#
|
||||
while (1) {
|
||||
# While there is an @" remove it and the next "@
|
||||
if (line ~ /@"/) {
|
||||
if (line ~ /@".*"@/) {
|
||||
# Do this special case first to avoid swallowing extra spaces
|
||||
# before or after the @ stuff:
|
||||
if (!sub(/@" *"@/, "", line)) {
|
||||
# Ok, do it in pieces - there has to be a non-space between the
|
||||
# two. NOTE: really weird things happen if a leading @" is
|
||||
# lost - the code will error out below (I believe).
|
||||
if (!sub(/@" */, "", line) || !sub(/ *"@/, "", line)) {
|
||||
print "line", lineno, ": internal error:", orig
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# There is no matching "@. Assume a split line
|
||||
else while (1) {
|
||||
if (getline nextline) {
|
||||
# If the line starts with '#' it is a preprocesor line directive
|
||||
# from cc -E; skip it:
|
||||
if (nextline !~ /^#/) {
|
||||
line = line " " nextline
|
||||
break
|
||||
}
|
||||
} else {
|
||||
# This is end-of-input - probably a missing "@ on the first line:
|
||||
print "line", lineno ": unbalanced @\" ... \"@ pair"
|
||||
err=1
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
# Keep going until all the @" have gone
|
||||
continue
|
||||
}
|
||||
|
||||
# Attempt to remove a trailing " (not preceded by '@') - if this can
|
||||
# be done, stop now; if not assume a split line again
|
||||
if (sub(/"[^"]*$/, "", line))
|
||||
break
|
||||
|
||||
# Read another line
|
||||
while (1) {
|
||||
if (getline nextline) {
|
||||
if (nextline !~ /^#/) {
|
||||
line = line " " nextline
|
||||
# Go back to stripping @" "@ pairs
|
||||
break
|
||||
}
|
||||
} else {
|
||||
print "line", lineno ": unterminated PNG_DFN string"
|
||||
err=1
|
||||
next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Put any needed double quotes in (at the end, because these would otherwise
|
||||
# interfere with the processing above.)
|
||||
gsub(/@'/,"\"", line)
|
||||
|
||||
# Remove any trailing spaces (not really required, but for
|
||||
# editorial consistency
|
||||
sub(/ *$/, "", line)
|
||||
|
||||
# Remove trailing CR
|
||||
sub(/
$/, "", line)
|
||||
|
||||
if (sort) {
|
||||
if (split(line, parts) < sort) {
|
||||
print "line", lineno ": missing sort field:", line
|
||||
err=1
|
||||
} else
|
||||
array[parts[sort]] = line
|
||||
}
|
||||
|
||||
else
|
||||
print line >out
|
||||
next
|
||||
}
|
||||
|
||||
/PNG_DFN/{
|
||||
print "line", NR, "incorrectly formatted PNG_DFN line:"
|
||||
print $0
|
||||
err = 1
|
||||
}
|
||||
|
||||
END{
|
||||
if (out_count > 0 || err > 0)
|
||||
exit err
|
||||
|
||||
print "no definition lines found"
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# genchk.cmake.in
|
||||
# Generate .chk from .out with awk (generic), based upon the automake logic.
|
||||
|
||||
# Copyright (C) 2016 Glenn Randers-Pehrson
|
||||
# Written by Roger Leigh, 2016
|
||||
|
||||
# This code is released under the libpng license.
|
||||
# For conditions of distribution and use, see the disclaimer
|
||||
# and license in png.h
|
||||
|
||||
# Variables substituted from CMakeLists.txt
|
||||
set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
|
||||
|
||||
set(AWK "@AWK@")
|
||||
|
||||
get_filename_component(INPUTEXT "${INPUT}" EXT)
|
||||
get_filename_component(OUTPUTEXT "${OUTPUT}" EXT)
|
||||
get_filename_component(INPUTBASE "${INPUT}" NAME_WE)
|
||||
get_filename_component(OUTPUTBASE "${OUTPUT}" NAME_WE)
|
||||
get_filename_component(INPUTDIR "${INPUT}" PATH)
|
||||
get_filename_component(OUTPUTDIR "${OUTPUT}" PATH)
|
||||
|
||||
if("${INPUTEXT}" STREQUAL ".out" AND "${OUTPUTEXT}" STREQUAL ".chk")
|
||||
# Generate .chk from .out with awk (generic)
|
||||
file(REMOVE "${OUTPUT}" "${OUTPUTDIR}/${OUTPUTBASE}.new")
|
||||
execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/checksym.awk"
|
||||
"${SRCDIR}/scripts/${INPUTBASE}.def"
|
||||
"of=${OUTPUTDIR}/${OUTPUTBASE}.new"
|
||||
"${INPUT}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate ${OUTPUTDIR}/${OUTPUTBASE}.new")
|
||||
endif()
|
||||
file(RENAME "${OUTPUTDIR}/${OUTPUTBASE}.new" "${OUTPUT}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported conversion: ${INPUTEXT} to ${OUTPUTEXT}")
|
||||
endif()
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
# genout.cmake.in
|
||||
# Generate .out from .c with awk (generic), based upon the automake logic.
|
||||
|
||||
# Copyright (C) 2016 Glenn Randers-Pehrson
|
||||
# Written by Roger Leigh, 2016
|
||||
|
||||
# This code is released under the libpng license.
|
||||
# For conditions of distribution and use, see the disclaimer
|
||||
# and license in png.h
|
||||
|
||||
# Variables substituted from CMakeLists.txt
|
||||
set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
|
||||
set(BINDIR "@CMAKE_CURRENT_BINARY_DIR@")
|
||||
|
||||
set(AWK "@AWK@")
|
||||
set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@")
|
||||
set(CMAKE_C_FLAGS @CMAKE_C_FLAGS@)
|
||||
set(INCDIR "@CMAKE_CURRENT_BINARY_DIR@")
|
||||
set(PNG_PREFIX "@PNG_PREFIX@")
|
||||
set(PNGLIB_MAJOR "@PNGLIB_MAJOR@")
|
||||
set(PNGLIB_MINOR "@PNGLIB_MINOR@")
|
||||
set(PNGLIB_VERSION "@PNGLIB_VERSION@")
|
||||
set(ZLIBINCDIR "@ZLIB_INCLUDE_DIR@")
|
||||
|
||||
set(PLATFORM_C_FLAGS)
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "@CMAKE_OSX_ARCHITECTURES@")
|
||||
set(CMAKE_OSX_SYSROOT "@CMAKE_OSX_SYSROOT@")
|
||||
if(CMAKE_OSX_ARCHITECTURES)
|
||||
set(PLATFORM_C_FLAGS ${PLATFORM_C_FLAGS} -arch ${CMAKE_OSX_ARCHITECTURES})
|
||||
endif()
|
||||
if(CMAKE_OSX_SYSROOT)
|
||||
set(PLATFORM_C_FLAGS ${PLATFORM_C_FLAGS} -isysroot ${CMAKE_OSX_SYSROOT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
get_filename_component(INPUTEXT "${INPUT}" EXT)
|
||||
get_filename_component(OUTPUTEXT "${OUTPUT}" EXT)
|
||||
get_filename_component(INPUTBASE "${INPUT}" NAME_WE)
|
||||
get_filename_component(OUTPUTBASE "${OUTPUT}" NAME_WE)
|
||||
get_filename_component(INPUTDIR "${INPUT}" PATH)
|
||||
get_filename_component(OUTPUTDIR "${OUTPUT}" PATH)
|
||||
|
||||
if ("${INPUTEXT}" STREQUAL ".c" AND "${OUTPUTEXT}" STREQUAL ".out")
|
||||
get_filename_component(GENDIR "${OUTPUT}" PATH)
|
||||
file(MAKE_DIRECTORY "${GENDIR}")
|
||||
|
||||
file(REMOVE "${OUTPUT}.tf1" "${OUTPUT}.tf2")
|
||||
|
||||
set(INCLUDES "-I${INCDIR}")
|
||||
if(ZLIBINCDIR)
|
||||
foreach(dir ${ZLIBINCDIR})
|
||||
list(APPEND INCLUDES "-I${dir}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(PNG_PREFIX)
|
||||
set(PNG_PREFIX_DEF "-DPNG_PREFIX=${PNG_PREFIX}")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E"
|
||||
${CMAKE_C_FLAGS}
|
||||
${PLATFORM_C_FLAGS}
|
||||
"-I${SRCDIR}"
|
||||
"-I${BINDIR}"
|
||||
${INCLUDES}
|
||||
"-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"
|
||||
${PNG_PREFIX_DEF}
|
||||
"${INPUT}"
|
||||
OUTPUT_FILE "${OUTPUT}.tf1"
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE CPP_FAIL)
|
||||
if(CPP_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate ${OUTPUT}.tf1")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/dfn.awk"
|
||||
"out=${OUTPUT}.tf2" "${OUTPUT}.tf1"
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate ${OUTPUT}.tf2")
|
||||
endif()
|
||||
|
||||
file(REMOVE "${OUTPUT}.tf1")
|
||||
file(RENAME "${OUTPUT}.tf2" "${OUTPUT}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported conversion: ${INPUTEXT} to ${OUTPUTEXT}")
|
||||
endif()
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
# gensrc.cmake.in
|
||||
# Generate source files with awk, based upon the automake logic.
|
||||
|
||||
# Copyright (C) 2016 Glenn Randers-Pehrson
|
||||
# Written by Roger Leigh, 2016
|
||||
|
||||
# This code is released under the libpng license.
|
||||
# For conditions of distribution and use, see the disclaimer
|
||||
# and license in png.h
|
||||
|
||||
# Variables substituted from CMakeLists.txt
|
||||
set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
|
||||
set(BINDIR "@CMAKE_CURRENT_BINARY_DIR@")
|
||||
|
||||
set(AWK "@AWK@")
|
||||
set(DFA_XTRA "@DFA_XTRA@")
|
||||
set(PNG_PREFIX "@PNG_PREFIX@")
|
||||
set(PNGLIB_VERSION "@PNGLIB_VERSION@")
|
||||
|
||||
if("${OUTPUT}" STREQUAL "scripts/pnglibconf.c")
|
||||
# Generate scripts/pnglibconf.c
|
||||
|
||||
file(REMOVE "${BINDIR}/pnglibconf.tf6" "${BINDIR}/pnglibconf.tf7")
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "com ${PNGLIB_VERSION} STANDARD API DEFINITION"
|
||||
COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
|
||||
"out=pnglibconf.tf6" "logunsupported=1" "version=search"
|
||||
"${SRCDIR}/pngconf.h" "-"
|
||||
"${SRCDIR}/scripts/pnglibconf.dfa"
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pnglibconf.tf6")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
|
||||
"out=pnglibconf.tf7" "pnglibconf.tf6"
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pnglibconf.tf7")
|
||||
endif()
|
||||
|
||||
file(REMOVE "pnglibconf.tf6")
|
||||
file(MAKE_DIRECTORY "${BINDIR}/scripts")
|
||||
file(RENAME "pnglibconf.tf7" "${BINDIR}/scripts/pnglibconf.c")
|
||||
|
||||
elseif ("${OUTPUT}" STREQUAL "pnglibconf.c")
|
||||
# Generate pnglibconf.c
|
||||
|
||||
file(REMOVE "${BINDIR}/pnglibconf.tf4" "${BINDIR}/pnglibconf.tf5")
|
||||
|
||||
execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
|
||||
out=pnglibconf.tf4 version=search
|
||||
${SRCDIR}/pngconf.h ${SRCDIR}/scripts/pnglibconf.dfa
|
||||
${SRCDIR}/pngusr.dfa ${DFA_XTRA}
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pnglibconf.tf4")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
|
||||
out=pnglibconf.tf5 pnglibconf.tf4
|
||||
WORKING_DIRECTORY "${BINDIR}"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pnglibconf.tf5")
|
||||
endif()
|
||||
|
||||
file(REMOVE "pnglibconf.tf4")
|
||||
file(MAKE_DIRECTORY "${BINDIR}/scripts")
|
||||
file(RENAME "pnglibconf.tf5" "${BINDIR}/pnglibconf.c")
|
||||
|
||||
elseif ("${OUTPUT}" STREQUAL "pnglibconf.h")
|
||||
# Generate pnglibconf.h
|
||||
|
||||
file(REMOVE "${BINDIR}/${OUTPUT}")
|
||||
if(PNG_PREFIX)
|
||||
file(REMOVE "pnglibconf.tf8")
|
||||
|
||||
execute_process(COMMAND "${AWK}" "s==0 && NR>1{print prev}
|
||||
s==0{prev=\$0}
|
||||
s==1{print \"#define\", \$1, \"${PNG_PREFIX}\" \$1}
|
||||
s==2{print \"#define ${PNG_PREFIX}png_\" \$1, \"PNG_\" \$1}
|
||||
END{print prev}" s=0 pnglibconf.out s=1 "${BINDIR}/scripts/prefix.out"
|
||||
s=2 "${SRCDIR}/scripts/macro.lst"
|
||||
OUTPUT_FILE pnglibconf.tf8
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pnglibconf.tf8")
|
||||
endif()
|
||||
|
||||
file(RENAME "pnglibconf.tf8" "${BINDIR}/${OUTPUT}")
|
||||
else()
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${BINDIR}/pnglibconf.out"
|
||||
"${BINDIR}/${OUTPUT}"
|
||||
RESULT_VARIABLE COPY_FAIL)
|
||||
if(COPY_FAIL)
|
||||
message(FATAL_ERROR "Failed to create pnglibconf.h")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
elseif ("${OUTPUT}" STREQUAL "pngprefix.h")
|
||||
# Generate pngprefix.h
|
||||
|
||||
file(REMOVE "${BINDIR}/${OUTPUT}")
|
||||
|
||||
if(PNG_PREFIX)
|
||||
file(REMOVE "pngprefix.tf1")
|
||||
|
||||
execute_process(COMMAND "${AWK}"
|
||||
"{print \"#define\", \$1, \"${PNG_PREFIX}\" \$1}"
|
||||
"${BINDIR}/scripts/intprefix.out"
|
||||
OUTPUT_FILE "pngprefix.tf1"
|
||||
RESULT_VARIABLE AWK_FAIL)
|
||||
if(AWK_FAIL)
|
||||
message(FATAL_ERROR "Failed to generate pngprefix.tf1")
|
||||
endif()
|
||||
|
||||
file(RENAME "pngprefix.tf1" "${BINDIR}/${OUTPUT}")
|
||||
else()
|
||||
file(WRITE "${BINDIR}/${OUTPUT}" "/* No libpng symbol prefix configured. */")
|
||||
endif()
|
||||
|
||||
elseif("${OUTPUT}" STREQUAL "scripts/pnglibconf.h.prebuilt")
|
||||
# Generate scripts/pnglibconf.h.prebuilt (fails build)
|
||||
|
||||
message(STATUS "Attempting to build scripts/pnglibconf.h.prebuilt")
|
||||
message(STATUS "This is a machine generated file, but if you want to make")
|
||||
message(STATUS "a new one simply build the 'genfiles' target, and copy")
|
||||
message(STATUS "scripts/pnglibconf.out to scripts/pnglibconf.h.prebuilt")
|
||||
message(STATUS "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)")
|
||||
message(FATAL_ERROR "Stopping build")
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported output: ${OUTPUT}")
|
||||
endif()
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue