From fa0b1cb5092bb1c2109ff870587a32b771179705 Mon Sep 17 00:00:00 2001 From: cutealien Date: Sat, 19 Dec 2020 15:03:11 +0000 Subject: [PATCH] Merging r6145 through r6171 from trunk to ogl-es branch git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6172 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 9 +- examples/Demo/CMainMenu.cpp | 20 +- include/IDynamicMeshBuffer.h | 10 +- include/IGUIButton.h | 4 + include/IGUIEnvironment.h | 19 +- include/IGUIStaticText.h | 4 + include/IImage.h | 35 + .../CBurningShader_Raster_Reference.cpp | 22 +- source/Irrlicht/CDepthBuffer.cpp | 18 +- source/Irrlicht/CDepthBuffer.h | 6 +- source/Irrlicht/CGUIButton.cpp | 12 +- source/Irrlicht/CGUIButton.h | 3 + source/Irrlicht/CGUIContextMenu.cpp | 4 +- source/Irrlicht/CGUIEnvironment.cpp | 41 +- source/Irrlicht/CGUIEnvironment.h | 10 +- source/Irrlicht/CGUIFont.cpp | 4 +- source/Irrlicht/CGUIStaticText.cpp | 16 +- source/Irrlicht/CGUIStaticText.h | 3 + source/Irrlicht/CGUITreeView.cpp | 15 +- source/Irrlicht/CIrrDeviceOSX.h | 14 +- source/Irrlicht/CNullDriver.cpp | 2 +- source/Irrlicht/CNullDriver.h | 2 +- source/Irrlicht/CSoftwareDriver2.cpp | 2100 ++++++++--------- source/Irrlicht/CSoftwareDriver2.h | 77 +- source/Irrlicht/CSoftwareTexture2.cpp | 219 +- source/Irrlicht/CSoftwareTexture2.h | 47 +- source/Irrlicht/CTRGouraud2.cpp | 22 +- source/Irrlicht/CTRGouraudAlpha2.cpp | 23 +- source/Irrlicht/CTRGouraudAlphaNoZ2.cpp | 22 +- source/Irrlicht/CTRGouraudNoZ2.cpp | 22 +- source/Irrlicht/CTRNormalMap.cpp | 19 +- source/Irrlicht/CTRStencilShadow.cpp | 19 +- source/Irrlicht/CTRTextureBlend.cpp | 89 +- source/Irrlicht/CTRTextureDetailMap2.cpp | 31 +- source/Irrlicht/CTRTextureGouraud2.cpp | 25 +- source/Irrlicht/CTRTextureGouraudAdd2.cpp | 22 +- source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp | 19 +- source/Irrlicht/CTRTextureGouraudAlpha.cpp | 23 +- source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp | 133 +- source/Irrlicht/CTRTextureGouraudNoZ2.cpp | 208 +- .../CTRTextureGouraudVertexAlpha2.cpp | 22 +- source/Irrlicht/CTRTextureLightMap2_Add.cpp | 22 +- source/Irrlicht/CTRTextureLightMap2_M1.cpp | 14 +- source/Irrlicht/CTRTextureLightMap2_M2.cpp | 16 +- source/Irrlicht/CTRTextureLightMap2_M4.cpp | 40 +- .../CTRTextureLightMapGouraud2_M4.cpp | 22 +- source/Irrlicht/CTRTextureWire2.cpp | 14 +- .../CTR_transparent_reflection_2_layer.cpp | 18 +- source/Irrlicht/IBurningShader.cpp | 102 +- source/Irrlicht/IBurningShader.h | 61 +- source/Irrlicht/IDepthBuffer.h | 4 +- source/Irrlicht/S4DVertex.h | 21 +- .../Irrlicht/SoftwareDriver2_compile_config.h | 331 +-- source/Irrlicht/SoftwareDriver2_helper.h | 67 +- .../burning_shader_compile_fragment_start.h | 6 +- .../burning_shader_compile_triangle.h | 11 +- source/Irrlicht/libpng/ANNOUNCE | 69 +- source/Irrlicht/libpng/AUTHORS | 45 + source/Irrlicht/libpng/CHANGES | 543 ++++- source/Irrlicht/libpng/CMakeLists.txt | 443 ++-- source/Irrlicht/libpng/INSTALL | 389 --- source/Irrlicht/libpng/LICENSE | 174 +- source/Irrlicht/libpng/README | 124 +- source/Irrlicht/libpng/TODO | 48 +- source/Irrlicht/libpng/TRADEMARK | 8 + source/Irrlicht/libpng/configure | 19 - source/Irrlicht/libpng/example.c | 475 ++-- source/Irrlicht/libpng/libpng-config.in | 127 - source/Irrlicht/libpng/libpng-manual.txt | 300 +-- source/Irrlicht/libpng/libpng.3 | 541 ++--- source/Irrlicht/libpng/libpng.pc.in | 11 - source/Irrlicht/libpng/libpngpf.3 | 18 +- source/Irrlicht/libpng/png.5 | 76 +- source/Irrlicht/libpng/png.c | 696 +++--- source/Irrlicht/libpng/png.h | 516 ++-- source/Irrlicht/libpng/pngconf.h | 91 +- source/Irrlicht/libpng/pngdebug.h | 6 +- source/Irrlicht/libpng/pngerror.c | 86 +- source/Irrlicht/libpng/pngget.c | 104 +- source/Irrlicht/libpng/pnginfo.h | 26 +- source/Irrlicht/libpng/pnglibconf.h | 432 ++-- source/Irrlicht/libpng/pngmem.c | 26 +- source/Irrlicht/libpng/pngpread.c | 76 +- source/Irrlicht/libpng/pngpriv.h | 498 ++-- source/Irrlicht/libpng/pngread.c | 387 +-- source/Irrlicht/libpng/pngrio.c | 18 +- source/Irrlicht/libpng/pngrtran.c | 2030 ++++++++-------- source/Irrlicht/libpng/pngrutil.c | 622 +++-- source/Irrlicht/libpng/pngset.c | 293 ++- source/Irrlicht/libpng/pngstruct.h | 38 +- source/Irrlicht/libpng/pngtest.c | 538 +++-- source/Irrlicht/libpng/pngtest.png | Bin 8695 -> 8759 bytes source/Irrlicht/libpng/pngtrans.c | 73 +- source/Irrlicht/libpng/pngusr.dfa | 14 + source/Irrlicht/libpng/pngwio.c | 16 +- source/Irrlicht/libpng/pngwrite.c | 198 +- source/Irrlicht/libpng/pngwtran.c | 25 +- source/Irrlicht/libpng/pngwutil.c | 432 ++-- tests/flyCircleAnimator.cpp | 2 +- tests/media/Burning's Video-2dmatFilter.png | Bin 25513 -> 18757 bytes .../Burning's Video-ambient-lighting.png | Bin 391 -> 392 bytes .../Burning's Video-draw2DImage4cFilter.png | Bin 35406 -> 23716 bytes tests/media/Burning's Video-drawPixel.png | Bin 27905 -> 27966 bytes tests/media/Burning's Video-multiTexture.png | Bin 8117 -> 7646 bytes tests/media/Burning's Video-orthoCam.png | Bin 4468 -> 4542 bytes ...Burning's Video-planeMatrix-scaledClip.png | Bin 37083 -> 40447 bytes tests/media/Burning's Video-renderMipmap.png | Bin 740 -> 814 bytes tests/media/Burning's Video-stencilShadow.png | Bin 3508 -> 3495 bytes tests/media/Burning's Video-terrainGap.png | Bin 4337 -> 3898 bytes .../Burning's Video-terrainSceneNode-1.png | Bin 34251 -> 39271 bytes .../Burning's Video-terrainSceneNode-2.png | Bin 36646 -> 41628 bytes .../Burning's Video-testGeometryCreator.png | Bin 8117 -> 8407 bytes .../media/Burning's Video-testTerrainMesh.png | Bin 32006 -> 33283 bytes .../media/Burning's Video-textureMatrix2.png | Bin 15212 -> 15190 bytes .../Burning's Video-textureRenderStates.png | Bin 27349 -> 30344 bytes .../Burning's Video-writeImageToFile.png | Bin 27905 -> 27966 bytes tests/tests-last-passed-at.txt | 4 +- 117 files changed, 8063 insertions(+), 6758 deletions(-) create mode 100644 source/Irrlicht/libpng/AUTHORS delete mode 100644 source/Irrlicht/libpng/INSTALL create mode 100644 source/Irrlicht/libpng/TRADEMARK delete mode 100644 source/Irrlicht/libpng/configure delete mode 100644 source/Irrlicht/libpng/libpng-config.in delete mode 100644 source/Irrlicht/libpng/libpng.pc.in create mode 100644 source/Irrlicht/libpng/pngusr.dfa diff --git a/changes.txt b/changes.txt index 74833877..808328dd 100644 --- a/changes.txt +++ b/changes.txt @@ -9,6 +9,9 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- Add getActiveColor functions to IGUIStaticText and IGUIButton (get currently used color). +- Add IGUIEnvironment::addToDeletionQueue to allow save removal of gui elements while iterating over them (like the same named function in ISceneManager). +- IGUIEnvironment::drawAll has now a parameter to allow disabling automatic resize to screensize. Makes it easier to use partial screens with full alignment support. - No longer try to set WM_QUIT when using an external Window on Win32. Thx @Marko Mahnic for the patch (https://sourceforge.net/p/irrlicht/bugs/449) - ply meshloader now also supports textures with uv-labels named texture_u/texture_v. @@ -22,15 +25,16 @@ Changes in 1.9 (not yet released) - Improvements to B3D writer for speed, readability and handling of low framerate animations. Thanks @JLouisB for the patch (For more info, see: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=2&t=50067&start=15) - Add another render pass ESNRP_GUI which is drawn last and is p.E. useful for rendering gui nodes in the scenemanager. -- BurningVideo: 0.51 +- BurningVideo: 0.52 - 10 year anniversary update - Lighting model reworked. moved to eyespace like openGL. [Specular Highlights, Fog, Sphere/Reflection Map] - increased internal s4DVertex to support 4 Textures and 4 Colors [switchable] - Textures are handled as sRGB during Mipmap Generation. More accurate, less visual disruption - - 2D is drawn as 3D like hardware drivers. [switchable]. enables viewport scaling, material2D + - 2D is drawn as 3D like hardware drivers. [switchable]. enables viewport scaling, material2D, scissor - Texture Spatial Resolution Limiting working. [lower memory consumption,SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE] - NormalMap for 1 Light accurate. still all lights are accumulated - SuperTuxKart 8.0.1 playable + - Internal Backbuffer Scaling and Interlacing - Known Problems - Depthbuffer range not equal to Hardware Drivers. Problems with Orthographic Stencil Shadows - Triangle MipMap Selection. Wrong for TextureAtlas and Billboards @@ -309,6 +313,7 @@ Changes in 1.9 (not yet released) -------------------------- Changes in 1.8.5 + - Update libpng to 1.6.37 (from 1.6.23) - Fix CIrrDeviceSDL::getVideoModeList which didn't return video modes before. Thx @kas1e for report and patch. - CIrrDeviceMacOSX now sets the SEvent.MouseInput Shift and Control values on mouse events like the other devices. Thanks @ Zero King for patch (#321) - isWindowFocused in IrrDeviceSDL device now returns the input focus like the other devices. Before it was returning a mouse-over-window state. diff --git a/examples/Demo/CMainMenu.cpp b/examples/Demo/CMainMenu.cpp index 432c8727..f67d9f3c 100644 --- a/examples/Demo/CMainMenu.cpp +++ b/examples/Demo/CMainMenu.cpp @@ -72,24 +72,14 @@ bool CMainMenu::run() // add list box gui::IGUIListBox* box = guienv->addListBox(core::rect(10,10,220,120), optTab, 1); - - const wchar_t* const names[] = - {L"Software Renderer", L"Burning's Video", - L"Direct3D 8", L"Direct3D 9", L"OpenGL 1.x-4.x", - L"OpenGL-ES 1.x", L"OpenGL-ES 2.x"}; for (u32 i=1; iaddItem(names[i-1]); - } - - switch (driverType ) - { - case video::EDT_OPENGL: selected = 0; break; - case video::EDT_DIRECT3D9: selected = 1; break; - case video::EDT_BURNINGSVIDEO: selected = 2; break; - case video::EDT_SOFTWARE: selected = 3; break; - default: break; + { + box->addItem(core::stringw(video::DRIVER_TYPE_NAMES[i]).c_str()); + if ( driverType == video::E_DRIVER_TYPE(i) ) + selected = box->getItemCount()-1; + } } box->setSelected(selected); diff --git a/include/IDynamicMeshBuffer.h b/include/IDynamicMeshBuffer.h index e7c4ffe5..7f9ee48f 100644 --- a/include/IDynamicMeshBuffer.h +++ b/include/IDynamicMeshBuffer.h @@ -26,23 +26,23 @@ namespace scene //! Get the material of this meshbuffer /** \return Material of this buffer. */ - virtual video::SMaterial& getMaterial() =0; + virtual video::SMaterial& getMaterial() _IRR_OVERRIDE_ =0; //! Get the material of this meshbuffer /** \return Material of this buffer. */ - virtual const video::SMaterial& getMaterial() const =0; + virtual const video::SMaterial& getMaterial() const _IRR_OVERRIDE_ =0; //! Get the axis aligned bounding box of this meshbuffer. /** \return Axis aligned bounding box of this buffer. */ - virtual const core::aabbox3df& getBoundingBox() const =0; + virtual const core::aabbox3df& getBoundingBox() const _IRR_OVERRIDE_ =0; //! Set axis aligned bounding box /** \param box User defined axis aligned bounding box to use for this buffer. */ - virtual void setBoundingBox(const core::aabbox3df& box) =0; + virtual void setBoundingBox(const core::aabbox3df& box) _IRR_OVERRIDE_ =0; //! Recalculates the bounding box. Should be called if the mesh changed. - virtual void recalculateBoundingBox() =0; + virtual void recalculateBoundingBox() _IRR_OVERRIDE_ =0; //! Append the vertices and indices to the current buffer /** Only works for compatible vertex types. diff --git a/include/IGUIButton.h b/include/IGUIButton.h index 1976adaf..88eb97bb 100644 --- a/include/IGUIButton.h +++ b/include/IGUIButton.h @@ -139,6 +139,10 @@ namespace gui /** \return: The override color */ virtual video::SColor getOverrideColor(void) const = 0; + //! Gets the currently used text color + /** Either a skin-color for the current state or the override color */ + virtual video::SColor getActiveColor() const = 0; + //! Sets if the button text should use the override color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIStaticText::setOverrideColor is used, otherwise the diff --git a/include/IGUIEnvironment.h b/include/IGUIEnvironment.h index 695b41b8..4bd3db87 100644 --- a/include/IGUIEnvironment.h +++ b/include/IGUIEnvironment.h @@ -74,7 +74,9 @@ class IGUIEnvironment : public virtual IReferenceCounted public: //! Draws all gui elements by traversing the GUI environment starting at the root node. - virtual void drawAll() = 0; + /** \param When true ensure the GuiEnvironment (aka the RootGUIElement) has the same size as the current driver screensize. + Can be set to false to control that size yourself, p.E when not the full size should be used for UI. */ + virtual void drawAll(bool useScreenSize=true) = 0; //! Sets the focus to an element. /** Causes a EGET_ELEMENT_FOCUS_LOST event followed by a @@ -621,10 +623,10 @@ public: virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)=0; //! writes an element - virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) =0; + virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* element) =0; //! reads an element - virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) =0; + virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* element) =0; //! Find the next element which would be selected when pressing the tab-key /** If you set the focus for the result you can manually force focus-changes like they @@ -644,6 +646,17 @@ public: //! Get the way the gui does handle focus changes /** \returns A bitmask which is a combination of ::EFOCUS_FLAG flags.*/ virtual u32 getFocusBehavior() const = 0; + + //! Adds a IGUIElement to deletion queue. + /** Queued elements will be removed at the end of each drawAll call. + Or latest in the destructor of the GUIEnvironment. + This can be used to allow an element removing itself safely in a function + iterating over gui elements, like an overloaded IGUIElement::draw or + IGUIElement::OnPostRender function. + Note that in general just calling IGUIElement::remove() is enough. + Unless you create your own GUI elements removing themselves you won't need it. + \param element: Element to remove */ + virtual void addToDeletionQueue(IGUIElement* element) = 0; }; diff --git a/include/IGUIStaticText.h b/include/IGUIStaticText.h index beb8f597..33db281e 100644 --- a/include/IGUIStaticText.h +++ b/include/IGUIStaticText.h @@ -51,6 +51,10 @@ namespace gui /** \return: The override color */ virtual video::SColor getOverrideColor(void) const = 0; + //! Gets the currently used text color + /** Either a skin-color for the current state or the override color */ + virtual video::SColor getActiveColor() const = 0; + //! Sets if the static text should use the override color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIStaticText::setOverrideColor is used, otherwise the diff --git a/include/IImage.h b/include/IImage.h index 09c40f42..3d4d5fa0 100644 --- a/include/IImage.h +++ b/include/IImage.h @@ -29,6 +29,9 @@ public: //! constructor IImage(ECOLOR_FORMAT format, const core::dimension2d& size, bool deleteMemory) : Format(format), Size(size), Data(0), MipMapsData(0), BytesPerPixel(0), Pitch(0), DeleteMemory(deleteMemory), DeleteMipMapsMemory(false) +#if defined(IRRLICHT_sRGB) + ,Format_sRGB(1) +#endif { BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8; Pitch = BytesPerPixel * Size.Width; @@ -50,6 +53,18 @@ public: return Format; } +#if defined(IRRLICHT_sRGB) + //! Texture is linear/sRGB (should be part of ColorFormat: default yes) + int get_sRGB() const + { + return Format_sRGB; + } + void set_sRGB(int val) + { + Format_sRGB = val; + } +#endif + //! Returns width and height of image data. const core::dimension2d& getDimension() const { @@ -534,6 +549,22 @@ public: return false; } +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) + { + switch (format) + { + case ECF_A1R5G5B5: + case ECF_R5G6B5: + case ECF_R8G8B8: + case ECF_A8R8G8B8: + return false; + default: + return true; + } + } +#endif + protected: ECOLOR_FORMAT Format; core::dimension2d Size; @@ -548,8 +579,12 @@ protected: bool DeleteMipMapsMemory; core::irrAllocator Allocator; +#if defined(IRRLICHT_sRGB) + int Format_sRGB; +#endif }; + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CBurningShader_Raster_Reference.cpp b/source/Irrlicht/CBurningShader_Raster_Reference.cpp index 3d9dacc6..45858a07 100644 --- a/source/Irrlicht/CBurningShader_Raster_Reference.cpp +++ b/source/Irrlicht/CBurningShader_Raster_Reference.cpp @@ -698,7 +698,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline2() return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); const f32 subPixel = ( (f32) pShader.xStart ) - line.x[0]; // store slopes in endpoint, and correct first pixel @@ -722,8 +722,8 @@ REALINLINE void CBurningShader_Raster_Reference::scanline2() } SOFTWARE_DRIVER_2_CLIPCHECK_REF; - pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); - pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); + pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY) ); + pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY) ); for ( pShader.i = 0; pShader.i <= pShader.dx; ++pShader.i ) { @@ -764,10 +764,10 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); + pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY) ); // subTexel const f32 subPixel = ( (f32) pShader.xStart ) - line.x[0]; @@ -807,7 +807,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () line.w[0] = a; line.w[1] = b; - pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); + pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY) ); a = (f32) pShader.i + subPixel; @@ -863,9 +863,9 @@ void CBurningShader_Raster_Reference::drawTriangle(const s4DVertex* burning_rest // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero2( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = reciprocal_zero2( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = reciprocal_zero2( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = fill_step_y( c->Pos.y - a->Pos.y ); + scan.invDeltaY[1] = fill_step_y( b->Pos.y - a->Pos.y ); + scan.invDeltaY[2] = fill_step_y( c->Pos.y - b->Pos.y ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -959,7 +959,7 @@ void CBurningShader_Raster_Reference::drawTriangle(const s4DVertex* burning_rest } // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.w[scan.left] = scan.w[0]; @@ -1076,7 +1076,7 @@ void CBurningShader_Raster_Reference::drawTriangle(const s4DVertex* burning_rest } // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.w[scan.left] = scan.w[0]; diff --git a/source/Irrlicht/CDepthBuffer.cpp b/source/Irrlicht/CDepthBuffer.cpp index eed72345..ec05bdab 100644 --- a/source/Irrlicht/CDepthBuffer.cpp +++ b/source/Irrlicht/CDepthBuffer.cpp @@ -40,7 +40,7 @@ CDepthBuffer::~CDepthBuffer() //! clears the zbuffer -void CDepthBuffer::clear(f32 value) +void CDepthBuffer::clear(f32 value, interlaced_control interlaced) { ieee754 zMaxValue; @@ -50,7 +50,7 @@ void CDepthBuffer::clear(f32 value) zMaxValue.f = value; #endif - memset32 ( Buffer, zMaxValue.u, TotalSize ); + memset32_interlaced(Buffer, zMaxValue.u, Pitch, Size.Height, interlaced); } @@ -66,9 +66,10 @@ void CDepthBuffer::setSize(const core::dimension2d& size) delete [] Buffer; Pitch = size.Width * sizeof ( fp24 ); - TotalSize = Pitch * size.Height; + size_t TotalSize = Pitch * size.Height; Buffer = new u8[align_next(TotalSize,16)]; - clear (); + + clear( 1.f, interlace_disabled()); } @@ -107,7 +108,7 @@ CStencilBuffer::~CStencilBuffer() //! clears the buffer -void CStencilBuffer::clear(u8 value) +void CStencilBuffer::clear(u32 value, const interlaced_control interlaced) { u32 set = value; if (Bit == 8) @@ -115,7 +116,7 @@ void CStencilBuffer::clear(u8 value) set |= set << 8; set |= set << 16; } - memset32 ( Buffer, set, TotalSize ); + memset32_interlaced ( Buffer, set, Pitch,Size.Height,interlaced ); } @@ -131,9 +132,10 @@ void CStencilBuffer::setSize(const core::dimension2d& size) delete [] Buffer; Pitch = size.Width * sizeof (tStencilSample); - TotalSize = Pitch * size.Height; + size_t TotalSize = Pitch * size.Height; Buffer = new u8[align_next(TotalSize,16)]; - clear (); + + clear(0, interlace_disabled()); } diff --git a/source/Irrlicht/CDepthBuffer.h b/source/Irrlicht/CDepthBuffer.h index aa9c33de..609f7a73 100644 --- a/source/Irrlicht/CDepthBuffer.h +++ b/source/Irrlicht/CDepthBuffer.h @@ -23,7 +23,7 @@ namespace video virtual ~CDepthBuffer(); //! clears the zbuffer - virtual void clear(f32 value=1.f) _IRR_OVERRIDE_; + virtual void clear(f32 value, const interlaced_control interlaced) _IRR_OVERRIDE_; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) _IRR_OVERRIDE_; @@ -45,7 +45,6 @@ namespace video u8* Buffer; core::dimension2d Size; - u32 TotalSize; u32 Pitch; }; @@ -61,7 +60,7 @@ namespace video virtual ~CStencilBuffer(); //! clears the zbuffer - virtual void clear(u8 value=0) _IRR_OVERRIDE_; + virtual void clear(u32 value, const interlaced_control interlaced) _IRR_OVERRIDE_; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) _IRR_OVERRIDE_; @@ -82,7 +81,6 @@ namespace video private: u8* Buffer; core::dimension2d Size; - u32 TotalSize; u32 Pitch; u32 Bit; }; diff --git a/source/Irrlicht/CGUIButton.cpp b/source/Irrlicht/CGUIButton.cpp index 895e31a2..95d2b37d 100644 --- a/source/Irrlicht/CGUIButton.cpp +++ b/source/Irrlicht/CGUIButton.cpp @@ -327,7 +327,7 @@ void CGUIButton::draw() if (font) font->draw(Text.c_str(), rect, - OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), + getActiveColor(), true, true, &AbsoluteClippingRect); } @@ -466,6 +466,16 @@ video::SColor CGUIButton::getOverrideColor() const return OverrideColor; } +irr::video::SColor CGUIButton::getActiveColor() const +{ + if ( OverrideColorEnabled ) + return OverrideColor; + IGUISkin* skin = Environment->getSkin(); + if (skin) + return OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT); + return OverrideColor; +} + void CGUIButton::enableOverrideColor(bool enable) { OverrideColorEnabled = enable; diff --git a/source/Irrlicht/CGUIButton.h b/source/Irrlicht/CGUIButton.h index ab383db7..88ca8f44 100644 --- a/source/Irrlicht/CGUIButton.h +++ b/source/Irrlicht/CGUIButton.h @@ -50,6 +50,9 @@ namespace gui //! Gets the override color virtual video::SColor getOverrideColor(void) const _IRR_OVERRIDE_; + //! Gets the currently used text color + virtual video::SColor getActiveColor() const _IRR_OVERRIDE_; + //! Sets if the button text should use the override color or the color in the gui skin. virtual void enableOverrideColor(bool enable) _IRR_OVERRIDE_; diff --git a/source/Irrlicht/CGUIContextMenu.cpp b/source/Irrlicht/CGUIContextMenu.cpp index 3a6484be..d38ceeda 100644 --- a/source/Irrlicht/CGUIContextMenu.cpp +++ b/source/Irrlicht/CGUIContextMenu.cpp @@ -136,10 +136,10 @@ void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) Items[index].SubMenu->drop(); Items[index].SubMenu = menu; - menu->setVisible(false); - if (Items[index].SubMenu) + if (menu) { + menu->setVisible(false); menu->AllowFocus = false; if ( Environment->getFocus() == menu ) { diff --git a/source/Irrlicht/CGUIEnvironment.cpp b/source/Irrlicht/CGUIEnvironment.cpp index e29195b2..e970d640 100644 --- a/source/Irrlicht/CGUIEnvironment.cpp +++ b/source/Irrlicht/CGUIEnvironment.cpp @@ -101,6 +101,8 @@ CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* drive //! destructor CGUIEnvironment::~CGUIEnvironment() { + clearDeletionQueue(); + if ( HoveredNoSubelement && HoveredNoSubelement != this ) { HoveredNoSubelement->drop(); @@ -191,19 +193,18 @@ void CGUIEnvironment::loadBuiltInFont() //! draws all gui elements -void CGUIEnvironment::drawAll() +void CGUIEnvironment::drawAll(bool useScreenSize) { - if (Driver) + if (useScreenSize && Driver) { core::dimension2d dim(Driver->getScreenSize()); if (AbsoluteRect.LowerRightCorner.X != dim.Width || - AbsoluteRect.LowerRightCorner.Y != dim.Height) + AbsoluteRect.UpperLeftCorner.X != 0 || + AbsoluteRect.LowerRightCorner.Y != dim.Height || + AbsoluteRect.UpperLeftCorner.Y != 0 + ) { - // resize gui environment - DesiredRect.LowerRightCorner = dim; - AbsoluteClippingRect = DesiredRect; - AbsoluteRect = DesiredRect; - updateAbsolutePosition(); + setRelativePosition(core::recti(0,0,dim.Width, dim.Height)); } } @@ -213,6 +214,8 @@ void CGUIEnvironment::drawAll() draw(); OnPostRender ( os::Timer::getTime () ); + + clearDeletionQueue(); } @@ -471,6 +474,28 @@ void CGUIEnvironment::OnPostRender( u32 time ) IGUIElement::OnPostRender ( time ); } +void CGUIEnvironment::addToDeletionQueue(IGUIElement* element) +{ + if (!element) + return; + + element->grab(); + DeletionQueue.push_back(element); +} + +void CGUIEnvironment::clearDeletionQueue() +{ + if (DeletionQueue.empty()) + return; + + for (u32 i=0; iremove(); + DeletionQueue[i]->drop(); + } + + DeletionQueue.clear(); +} // void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) diff --git a/source/Irrlicht/CGUIEnvironment.h b/source/Irrlicht/CGUIEnvironment.h index 58b7f545..e87e236f 100644 --- a/source/Irrlicht/CGUIEnvironment.h +++ b/source/Irrlicht/CGUIEnvironment.h @@ -31,7 +31,7 @@ public: virtual ~CGUIEnvironment(); //! draws all gui elements - virtual void drawAll() _IRR_OVERRIDE_; + virtual void drawAll(bool useScreenSize) _IRR_OVERRIDE_; //! returns the current video driver virtual video::IVideoDriver* getVideoDriver() const _IRR_OVERRIDE_; @@ -269,8 +269,14 @@ public: //! Get the way the gui does handle focus changes virtual u32 getFocusBehavior() const _IRR_OVERRIDE_; + //! Adds a IGUIElement to deletion queue. + virtual void addToDeletionQueue(IGUIElement* element) _IRR_OVERRIDE_; + private: + //! clears the deletion queue + void clearDeletionQueue(); + void updateHoveredElement(core::position2d mousePos); void loadBuiltInFont(); @@ -322,6 +328,8 @@ private: IEventReceiver* UserReceiver; IOSOperator* Operator; u32 FocusFlags; + core::array DeletionQueue; + static const io::path DefaultFontName; }; diff --git a/source/Irrlicht/CGUIFont.cpp b/source/Irrlicht/CGUIFont.cpp index 08579244..0fa82981 100644 --- a/source/Irrlicht/CGUIFont.cpp +++ b/source/Irrlicht/CGUIFont.cpp @@ -203,17 +203,15 @@ void CGUIFont::setMaxHeight() return; MaxHeight = 0; - s32 t; core::array< core::rect >& p = SpriteBank->getPositions(); for (u32 i=0; iMaxHeight) MaxHeight = t; } - } void CGUIFont::pushTextureCreationFlags(bool(&flags)[3]) diff --git a/source/Irrlicht/CGUIStaticText.cpp b/source/Irrlicht/CGUIStaticText.cpp index fc26a1a9..086c357d 100644 --- a/source/Irrlicht/CGUIStaticText.cpp +++ b/source/Irrlicht/CGUIStaticText.cpp @@ -99,8 +99,8 @@ void CGUIStaticText::draw() font->getDimension(Text.c_str()).Width; } - font->draw(Text.c_str(), frameRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), + font->draw(Text.c_str(), frameRect, + getActiveColor(), HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } else @@ -129,7 +129,7 @@ void CGUIStaticText::draw() } font->draw(BrokenText[i].c_str(), r, - OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), + getActiveColor(), HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); r.LowerRightCorner.Y += height; @@ -254,6 +254,16 @@ video::SColor CGUIStaticText::getOverrideColor() const } +irr::video::SColor CGUIStaticText::getActiveColor() const +{ + if ( OverrideColorEnabled ) + return OverrideColor; + IGUISkin* skin = Environment->getSkin(); + if (skin) + return OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT); + return OverrideColor; +} + //! Sets if the static text should use the override color or the //! color in the gui skin. void CGUIStaticText::enableOverrideColor(bool enable) diff --git a/source/Irrlicht/CGUIStaticText.h b/source/Irrlicht/CGUIStaticText.h index 7ca74019..b7fbf738 100644 --- a/source/Irrlicht/CGUIStaticText.h +++ b/source/Irrlicht/CGUIStaticText.h @@ -66,6 +66,9 @@ namespace gui //! Gets the override color virtual video::SColor getOverrideColor() const _IRR_OVERRIDE_; + //! Gets the currently used text color + virtual video::SColor getActiveColor() const _IRR_OVERRIDE_; + //! Sets if the static text should use the override color or the //! color in the gui skin. virtual void enableOverrideColor(bool enable) _IRR_OVERRIDE_; diff --git a/source/Irrlicht/CGUITreeView.cpp b/source/Irrlicht/CGUITreeView.cpp index f6d7743a..b348a791 100644 --- a/source/Irrlicht/CGUITreeView.cpp +++ b/source/Irrlicht/CGUITreeView.cpp @@ -264,9 +264,7 @@ IGUITreeViewNode* CGUITreeViewNode::getNextSibling() const IGUITreeViewNode* CGUITreeViewNode::getNextVisible() const { IGUITreeViewNode* next = 0; - IGUITreeViewNode* node = 0; - - node = const_cast( this ); + const IGUITreeViewNode* node = this; if( node->getExpanded() && node->hasChildren() ) { @@ -756,10 +754,7 @@ bool CGUITreeView::OnEvent( const SEvent &event ) void CGUITreeView::mouseAction( s32 xpos, s32 ypos, bool onlyHover /*= false*/ ) { IGUITreeViewNode* oldSelected = Selected; - IGUITreeViewNode* hitNode = 0; s32 selIdx=-1; - s32 n; - IGUITreeViewNode* node; SEvent event; event.EventType = EET_GUI_EVENT; @@ -776,9 +771,9 @@ void CGUITreeView::mouseAction( s32 xpos, s32 ypos, bool onlyHover /*= false*/ ) selIdx = ( ( ypos - 1 ) + scrollBarVPos ) / ItemHeight; } - hitNode = 0; - node = Root->getFirstChild(); - n = 0; + IGUITreeViewNode* hitNode = 0; + IGUITreeViewNode* node = Root->getFirstChild(); + s32 n = 0; while( node ) { if( selIdx == n ) @@ -1026,7 +1021,7 @@ void CGUITreeView::draw() iconWidth += ImageList->getImageSize().Width + 3; textRect.UpperLeftCorner.X += ImageList->getImageSize().Width + 3; } - else if( ( IconFont && reinterpret_cast( node )->Icon.size() ) + else if( ( IconFont && static_cast( node )->Icon.size() ) && ( ( ImageLeftOfIcon && n == 1 ) || ( !ImageLeftOfIcon && n == 0 ) ) ) { diff --git a/source/Irrlicht/CIrrDeviceOSX.h b/source/Irrlicht/CIrrDeviceOSX.h index d5378c82..7c34ce46 100644 --- a/source/Irrlicht/CIrrDeviceOSX.h +++ b/source/Irrlicht/CIrrDeviceOSX.h @@ -131,39 +131,39 @@ namespace irr } //! Changes the visible state of the mouse cursor. - virtual void setVisible(bool visible) + virtual void setVisible(bool visible) _IRR_OVERRIDE_ { IsVisible = visible; Device->setCursorVisible(visible); } //! Returns if the cursor is currently visible. - virtual bool isVisible() const + virtual bool isVisible() const _IRR_OVERRIDE_ { return IsVisible; } //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) + virtual void setPosition(const core::position2d &pos) _IRR_OVERRIDE_ { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. - virtual void setPosition(f32 x, f32 y) + virtual void setPosition(f32 x, f32 y) _IRR_OVERRIDE_ { setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); } //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) + virtual void setPosition(const core::position2d &pos) _IRR_OVERRIDE_ { if (CursorPos.X != pos.X || CursorPos.Y != pos.Y) setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. - virtual void setPosition(s32 x, s32 y) + virtual void setPosition(s32 x, s32 y) _IRR_OVERRIDE_ { if (UseReferenceRect) { @@ -195,7 +195,7 @@ namespace irr } //! Sets an absolute reference rect for calculating the cursor position. - virtual void setReferenceRect(core::rect* rect=0) + virtual void setReferenceRect(core::rect* rect=0) _IRR_OVERRIDE_ { if (rect) { diff --git a/source/Irrlicht/CNullDriver.cpp b/source/Irrlicht/CNullDriver.cpp index 23110e33..87a51df4 100644 --- a/source/Irrlicht/CNullDriver.cpp +++ b/source/Irrlicht/CNullDriver.cpp @@ -1076,7 +1076,7 @@ const wchar_t* CNullDriver::getName() const //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do -//! this: Frist, draw all geometry. Then use this method, to draw the shadow +//! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. void CNullDriver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { diff --git a/source/Irrlicht/CNullDriver.h b/source/Irrlicht/CNullDriver.h index ebd700de..11191661 100644 --- a/source/Irrlicht/CNullDriver.h +++ b/source/Irrlicht/CNullDriver.h @@ -288,7 +288,7 @@ namespace video virtual void addExternalImageWriter(IImageWriter* writer) _IRR_OVERRIDE_; //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do - //! this: Frist, draw all geometry. Then use this method, to draw the shadow + //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0) _IRR_OVERRIDE_; diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index 666c9849..605b15b4 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -39,25 +39,25 @@ bool mat44_transposed_inverse(irr::core::CMatrix4& out, const irr::core::CMat d = 1.0 / d; T* burning_restrict o = out.pointer(); - o[0] = (T)(d*(m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); - o[4] = (T)(d*(m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); - o[8] = (T)(d*(m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); - o[12] = (T)(d*(m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); + o[0] = (T)(d * (m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); + o[4] = (T)(d * (m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); + o[8] = (T)(d * (m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); + o[12] = (T)(d * (m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); - o[1] = (T)(d*(m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); - o[5] = (T)(d*(m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); - o[9] = (T)(d*(m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); - o[13] = (T)(d*(m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); + o[1] = (T)(d * (m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); + o[5] = (T)(d * (m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); + o[9] = (T)(d * (m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); + o[13] = (T)(d * (m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); - o[2] = (T)(d*(m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); - o[6] = (T)(d*(m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); - o[10] = (T)(d*(m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); - o[14] = (T)(d*(m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); + o[2] = (T)(d * (m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); + o[6] = (T)(d * (m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); + o[10] = (T)(d * (m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); + o[14] = (T)(d * (m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); - o[3] = (T)(d*(m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); - o[7] = (T)(d*(m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); - o[11] = (T)(d*(m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); - o[15] = (T)(d*(m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); + o[3] = (T)(d * (m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); + o[7] = (T)(d * (m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); + o[11] = (T)(d * (m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); + o[15] = (T)(d * (m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); return true; } @@ -85,25 +85,25 @@ bool mat44_inverse(CMatrix4& out, const CMatrix4& M) d = 1.0 / d; T* o = out.pointer(); - o[0] = (T)(d*(m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); - o[1] = (T)(d*(m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); - o[2] = (T)(d*(m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); - o[3] = (T)(d*(m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); + o[0] = (T)(d * (m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); + o[1] = (T)(d * (m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); + o[2] = (T)(d * (m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); + o[3] = (T)(d * (m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); - o[4] = (T)(d*(m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); - o[5] = (T)(d*(m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); - o[6] = (T)(d*(m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); - o[7] = (T)(d*(m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); + o[4] = (T)(d * (m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); + o[5] = (T)(d * (m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); + o[6] = (T)(d * (m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); + o[7] = (T)(d * (m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); - o[8] = (T)(d*(m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); - o[9] = (T)(d*(m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); - o[10] = (T)(d*(m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); - o[11] = (T)(d*(m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); + o[8] = (T)(d * (m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); + o[9] = (T)(d * (m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); + o[10] = (T)(d * (m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); + o[11] = (T)(d * (m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); - o[12] = (T)(d*(m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); - o[13] = (T)(d*(m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); - o[14] = (T)(d*(m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); - o[15] = (T)(d*(m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); + o[12] = (T)(d * (m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); + o[13] = (T)(d * (m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); + o[14] = (T)(d * (m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); + o[15] = (T)(d * (m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); return true; } @@ -115,8 +115,8 @@ inline void transformVec4Vec4(const irr::core::CMatrix4& m, T* burning_restri { const T* burning_restrict M = m.pointer(); - out[0] = in[0] * M[0] + in[1] * M[4] + in[2] * M[8] + in[3] * M[12]; - out[1] = in[0] * M[1] + in[1] * M[5] + in[2] * M[9] + in[3] * M[13]; + out[0] = in[0] * M[0] + in[1] * M[4] + in[2] * M[8] + in[3] * M[12]; + out[1] = in[0] * M[1] + in[1] * M[5] + in[2] * M[9] + in[3] * M[13]; out[2] = in[0] * M[2] + in[1] * M[6] + in[2] * M[10] + in[3] * M[14]; out[3] = in[0] * M[3] + in[1] * M[7] + in[2] * M[11] + in[3] * M[15]; } @@ -124,13 +124,13 @@ inline void transformVec4Vec4(const irr::core::CMatrix4& m, T* burning_restri #if 0 // void CMatrix4::transformVect(T *out, const core::vector3df &in) const template -inline void transformVec3Vec4(const irr::core::CMatrix4& m,T* burning_restrict out, const core::vector3df &in) +inline void transformVec3Vec4(const irr::core::CMatrix4& m, T* burning_restrict out, const core::vector3df& in) { const T* burning_restrict M = m.pointer(); - out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; - out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; - out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; - out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; + out[0] = in.X * M[0] + in.Y * M[4] + in.Z * M[8] + M[12]; + out[1] = in.X * M[1] + in.Y * M[5] + in.Z * M[9] + M[13]; + out[2] = in.X * M[2] + in.Y * M[6] + in.Z * M[10] + M[14]; + out[3] = in.X * M[3] + in.Y * M[7] + in.Z * M[11] + M[15]; } #endif @@ -172,105 +172,78 @@ static inline float powf_limit(const float a, const float b) return r; } - -#if defined(Tweak_Burning) - -// run time parameter -struct tweakBurning +//! clamp(value,0,1) +static inline const float clampf01(const float v) { - tweakBurning() + return v < 0.f ? 0.f : v > 1.f ? 1.f : v; +} + +// IImage::fill +static void image_fill(irr::video::IImage* image, const irr::video::SColor& color, const interlaced_control interlaced) +{ + if (0 == image) + return; + + unsigned int c = color.color; + + switch (image->getColorFormat()) { - current = 11; - step = 0.0001f; - - ndc_shrink_x = -0.75f; - ndc_scale_x = 0.5f; - ndc_trans_x = -0.5f; - - ndc_shrink_y = -0.75f; - ndc_scale_y = -0.5f; - ndc_trans_y = -0.5f; - - tex_w_add = 0.f; - tex_h_add = 0.f; - tex_cx_add = 0.f; - tex_cy_add = 0.f; - - AreaMinDrawSize = 0.001f; + case irr::video::ECF_A1R5G5B5: + c = color.toA1R5G5B5(); + c |= c << 16; + break; + default: + break; } - int current; + irr::memset32_interlaced(image->getData(), c, image->getPitch(), image->getDimension().Height, interlaced); +} - union + +union scale_setup +{ + struct { - struct { - f32 step; - - f32 ndc_shrink_x; - f32 ndc_scale_x; - f32 ndc_trans_x; - - f32 ndc_shrink_y; - f32 ndc_scale_y; - f32 ndc_trans_y; - - f32 tex_w_add; - f32 tex_cx_add; - f32 tex_h_add; - f32 tex_cy_add; - - f32 AreaMinDrawSize; //! minimal visible covered area for primitive - }; - f32 val[16]; + unsigned char x : 3; + unsigned char y : 3; + unsigned char i : 2; }; - static const char* const name[16]; - void postEventFromUser(const SEvent& e); + unsigned char v; }; -const char* const tweakBurning::name[] = { "step", - "ndc_shrink_x","ndc_scale_x","ndc_trans_x", - "ndc_shrink_y","ndc_scale_y","ndc_trans_y", - "tex_w_add","tex_cx_add","tex_h_add","tex_cy_add", - "dc_area",0 }; - -void tweakBurning::postEventFromUser(const SEvent& e) +//setup Antialias. v0.52 uses as Interlaced +void get_scale(scale_setup& s, const irr::SIrrlichtCreationParameters& params) { - int show = 0; - if (e.EventType == EET_KEY_INPUT_EVENT) + s.x = 1; + s.y = 1; + s.i = 0; + if (params.AntiAlias && params.WindowSize.Width <= 160 && params.WindowSize.Height <= 120) { - switch (e.KeyInput.Key) - { - case KEY_KEY_1: step *= 0.9f; if (step < 0.00001f) step = 0.0001f; show = 2; break; - case KEY_KEY_2: step *= 1.1f; show = 2; break; - - case KEY_KEY_3: if (!e.KeyInput.PressedDown) { current -= 1; if (current < 1) current = 11; show = 1; } break; - case KEY_KEY_4: if (!e.KeyInput.PressedDown) { current += 1; if (current > 11) current = 1; show = 1; } break; - - case KEY_KEY_5: val[current] -= e.KeyInput.Shift ? step * 100.f : step; show = 1; break; - case KEY_KEY_6: val[current] += e.KeyInput.Shift ? step * 100.f : step; show = 1; break; - default: - break; - } + return; } - if (show) + + switch (params.AntiAlias) { - if (step < 0.0001f) step = 0.0001f; - char buf[256]; - if (show == 2) sprintf(buf, "%s %f\n", name[0], val[0]); - else sprintf(buf, "%s %f\n", name[current], val[current]); - os::Printer::print(buf); + case 2: s.x = 1; s.y = 1; s.i = 1; break; + case 4: s.x = 2; s.y = 2; s.i = 0; break; + case 8: s.x = 2; s.y = 2; s.i = 1; break; + case 16:s.x = 4; s.y = 4; s.i = 0; break; + case 32:s.x = 4; s.y = 4; s.i = 1; break; + + case 3: s.x = 3; s.y = 3; s.i = 0; break; + case 5: s.x = 3; s.y = 3; s.i = 1; break; } } -void CBurningVideoDriver::postEventFromUser(const void* sevent) +//turn on/off fpu exception +void fpu_exception(int on) { - if (sevent) Tweak.postEventFromUser(*(const SEvent*)sevent); + return; +#if defined(_WIN32) + _clearfp(); + _controlfp(on ? _EM_INEXACT : -1, _MCW_EM); +#endif } -tweakBurning Tweak; -#endif //defined(Tweak_Burning) - - - namespace irr { namespace video @@ -278,51 +251,62 @@ namespace video //! constructor CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter) -: CNullDriver(io, params.WindowSize), BackBuffer(0), Presenter(presenter), + : CNullDriver(io, params.WindowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentShader(0), - DepthBuffer(0), StencilBuffer ( 0 ) + DepthBuffer(0), StencilBuffer(0) { //enable fpu exception - //unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM); + fpu_exception(1); - #ifdef _DEBUG +#ifdef _DEBUG setDebugName("CBurningVideoDriver"); - #endif +#endif VertexCache_map_source_format(); - // create backbuffer - BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, params.WindowSize); + //Use AntiAlias(hack) to shrink BackBuffer Size and keep ScreenSize the same as Input + scale_setup scale; + get_scale(scale, params); + + //Control Interlaced BackBuffer + Interlaced.enable = scale.i; + Interlaced.bypass = !Interlaced.enable; + Interlaced.nr = 0; + + // create backbuffer. + core::dimension2du use(params.WindowSize.Width / scale.x, params.WindowSize.Height / scale.y); + BackBuffer = new CImage(SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT, use); if (BackBuffer) { - BackBuffer->fill(SColor(0)); + //BackBuffer->fill(SColor(0)); + image_fill(BackBuffer, SColor(0), interlace_disabled()); // create z buffer - if ( params.ZBufferBits ) + if (params.ZBufferBits) DepthBuffer = video::createDepthBuffer(BackBuffer->getDimension()); // create stencil buffer - if ( params.Stencilbuffer ) - StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension(),8); + if (params.Stencilbuffer) + StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension(), 8); } - DriverAttributes->setAttribute("MaxIndices", 1<<16); + DriverAttributes->setAttribute("MaxIndices", 1 << 16); DriverAttributes->setAttribute("MaxTextures", BURNING_MATERIAL_MAX_TEXTURES); - DriverAttributes->setAttribute("MaxTextureSize", SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1<<20); - DriverAttributes->setAttribute("MaxLights", 1024 ); //glsl::gl_MaxLights); + DriverAttributes->setAttribute("MaxTextureSize", SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); + DriverAttributes->setAttribute("MaxLights", 1024); //glsl::gl_MaxLights); DriverAttributes->setAttribute("MaxTextureLODBias", 16.f); DriverAttributes->setAttribute("Version", 50); // create triangle renderers - memset( BurningShader, 0, sizeof ( BurningShader ) ); + memset(BurningShader, 0, sizeof(BurningShader)); //BurningShader[ETR_FLAT] = createTRFlat2(DepthBuffer); //BurningShader[ETR_FLAT_WIRE] = createTRFlatWire2(DepthBuffer); BurningShader[ETR_GOURAUD] = createTriangleRendererGouraud2(this); BurningShader[ETR_GOURAUD_NOZ] = createTriangleRendererGouraudNoZ2(this); //BurningShader[ETR_GOURAUD_ALPHA] = createTriangleRendererGouraudAlpha2(this ); - BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this ); // 2D + BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this); // 2D //BurningShader[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer); @@ -338,14 +322,14 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& BurningShader[ETR_TEXTURE_GOURAUD_NOZ] = createTRTextureGouraudNoZ2(this); BurningShader[ETR_TEXTURE_GOURAUD_ADD] = createTRTextureGouraudAdd2(this); BurningShader[ETR_TEXTURE_GOURAUD_ADD_NO_Z] = createTRTextureGouraudAddNoZ2(this); - BurningShader[ETR_TEXTURE_GOURAUD_VERTEX_ALPHA] = createTriangleRendererTextureVertexAlpha2 ( this ); + BurningShader[ETR_TEXTURE_GOURAUD_VERTEX_ALPHA] = createTriangleRendererTextureVertexAlpha2(this); - BurningShader[ETR_TEXTURE_GOURAUD_ALPHA] = createTRTextureGouraudAlpha(this ); - BurningShader[ETR_TEXTURE_GOURAUD_ALPHA_NOZ] = createTRTextureGouraudAlphaNoZ( this ); + BurningShader[ETR_TEXTURE_GOURAUD_ALPHA] = createTRTextureGouraudAlpha(this); + BurningShader[ETR_TEXTURE_GOURAUD_ALPHA_NOZ] = createTRTextureGouraudAlphaNoZ(this); - BurningShader[ETR_NORMAL_MAP_SOLID] = createTRNormalMap ( this ); - BurningShader[ETR_STENCIL_SHADOW] = createTRStencilShadow ( this ); - BurningShader[ETR_TEXTURE_BLEND] = createTRTextureBlend( this ); + BurningShader[ETR_NORMAL_MAP_SOLID] = createTRNormalMap(this); + BurningShader[ETR_STENCIL_SHADOW] = createTRStencilShadow(this); + BurningShader[ETR_TEXTURE_BLEND] = createTRTextureBlend(this); BurningShader[ETR_TRANSPARENT_REFLECTION_2_LAYER] = createTriangleRendererTexture_transparent_reflection_2_layer(this); //BurningShader[ETR_REFERENCE] = createTriangleRendererReference ( this ); @@ -353,42 +337,42 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& BurningShader[ETR_COLOR] = create_burning_shader_color(this); // add the same renderer for all solid types - CSoftware2MaterialRenderer_SOLID* smr = new CSoftware2MaterialRenderer_SOLID( this); - CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR* tmr = new CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR( this); + CSoftware2MaterialRenderer_SOLID* smr = new CSoftware2MaterialRenderer_SOLID(this); + CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR* tmr = new CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR(this); //CSoftware2MaterialRenderer_UNSUPPORTED * umr = new CSoftware2MaterialRenderer_UNSUPPORTED ( this ); //!TODO: addMaterialRenderer depends on pushing order.... - addMaterialRenderer ( smr ); // EMT_SOLID - addMaterialRenderer ( smr ); // EMT_SOLID_2_LAYER, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP, - addMaterialRenderer ( tmr ); // EMT_LIGHTMAP_ADD, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M2, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M4, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M2, - addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M4, - addMaterialRenderer ( smr ); // EMT_DETAIL_MAP, - addMaterialRenderer ( smr ); // EMT_SPHERE_MAP, - addMaterialRenderer ( smr ); // EMT_REFLECTION_2_LAYER, - addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ADD_COLOR, - addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL, - addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL_REF, - addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_VERTEX_ALPHA, - addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_REFLECTION_2_LAYER, - addMaterialRenderer ( smr ); // EMT_NORMAL_MAP_SOLID, - addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, - addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, - addMaterialRenderer ( smr ); // EMT_PARALLAX_MAP_SOLID, - addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, - addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, - addMaterialRenderer ( tmr ); // EMT_ONETEXTURE_BLEND + addMaterialRenderer(smr); // EMT_SOLID + addMaterialRenderer(smr); // EMT_SOLID_2_LAYER, + addMaterialRenderer(smr); // EMT_LIGHTMAP, + addMaterialRenderer(tmr); // EMT_LIGHTMAP_ADD, + addMaterialRenderer(smr); // EMT_LIGHTMAP_M2, + addMaterialRenderer(smr); // EMT_LIGHTMAP_M4, + addMaterialRenderer(smr); // EMT_LIGHTMAP_LIGHTING, + addMaterialRenderer(smr); // EMT_LIGHTMAP_LIGHTING_M2, + addMaterialRenderer(smr); // EMT_LIGHTMAP_LIGHTING_M4, + addMaterialRenderer(smr); // EMT_DETAIL_MAP, + addMaterialRenderer(smr); // EMT_SPHERE_MAP, + addMaterialRenderer(smr); // EMT_REFLECTION_2_LAYER, + addMaterialRenderer(tmr); // EMT_TRANSPARENT_ADD_COLOR, + addMaterialRenderer(tmr); // EMT_TRANSPARENT_ALPHA_CHANNEL, + addMaterialRenderer(tmr); // EMT_TRANSPARENT_ALPHA_CHANNEL_REF, + addMaterialRenderer(tmr); // EMT_TRANSPARENT_VERTEX_ALPHA, + addMaterialRenderer(tmr); // EMT_TRANSPARENT_REFLECTION_2_LAYER, + addMaterialRenderer(smr); // EMT_NORMAL_MAP_SOLID, + addMaterialRenderer(tmr); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, + addMaterialRenderer(tmr); // EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, + addMaterialRenderer(smr); // EMT_PARALLAX_MAP_SOLID, + addMaterialRenderer(tmr); // EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, + addMaterialRenderer(tmr); // EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, + addMaterialRenderer(tmr); // EMT_ONETEXTURE_BLEND - smr->drop (); - tmr->drop (); + smr->drop(); + tmr->drop(); //umr->drop (); // select render target - setRenderTargetImage(BackBuffer); + setRenderTargetImage2(BackBuffer,0, 0); //reset Lightspace EyeSpace.reset(); @@ -410,7 +394,7 @@ CBurningVideoDriver::~CBurningVideoDriver() } // delete triangle renderers - for (s32 i=0; idrop(); RenderTargetSurface = 0; } + + fpu_exception(0); + } @@ -458,7 +445,7 @@ bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const on = 1; break; #endif -#ifdef SOFTWARE_DRIVER_2_MIPMAPPING +#if SOFTWARE_DRIVER_2_MIPMAPPING_MAX > 1 case EVDF_MIP_MAP: on = 1; break; @@ -510,85 +497,74 @@ bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const } - -//! Create render target. -IRenderTarget* CBurningVideoDriver::addRenderTarget() -{ - CSoftwareRenderTarget2* renderTarget = new CSoftwareRenderTarget2(this); - RenderTargets.push_back(renderTarget); - - return renderTarget; -} - - //matrix multiplication void CBurningVideoDriver::transform_calc(E_TRANSFORMATION_STATE_BURNING_VIDEO state) { size_t* flag = TransformationFlag[TransformationStack]; - if (flag[state] & ETF_VALID ) return; + if (flag[state] & ETF_VALID) return; //check - int ok = 0; - switch ( state ) + size_t ok = 0; + switch (state) { - case ETS_PROJ_MODEL_VIEW: - if ( 0 == (flag[ETS_VIEW_PROJECTION] & ETF_VALID) ) transform_calc (ETS_VIEW_PROJECTION); - ok = flag[ETS_WORLD] & flag[ETS_VIEW] & flag[ETS_PROJECTION] & flag[ETS_VIEW_PROJECTION] & ETF_VALID; - break; - case ETS_VIEW_PROJECTION: - ok = flag[ETS_VIEW] & flag[ETS_PROJECTION] & ETF_VALID; - break; - case ETS_MODEL_VIEW: - ok = flag[ETS_WORLD] & flag[ETS_VIEW] & ETF_VALID; - break; - case ETS_NORMAL: - ok = flag[ETS_MODEL_VIEW] & ETF_VALID; - break; - default: - break; + case ETS_PROJ_MODEL_VIEW: + if (0 == (flag[ETS_VIEW_PROJECTION] & ETF_VALID)) transform_calc(ETS_VIEW_PROJECTION); + ok = flag[ETS_WORLD] & flag[ETS_VIEW] & flag[ETS_PROJECTION] & flag[ETS_VIEW_PROJECTION] & ETF_VALID; + break; + case ETS_VIEW_PROJECTION: + ok = flag[ETS_VIEW] & flag[ETS_PROJECTION] & ETF_VALID; + break; + case ETS_MODEL_VIEW: + ok = flag[ETS_WORLD] & flag[ETS_VIEW] & ETF_VALID; + break; + case ETS_NORMAL: + ok = flag[ETS_MODEL_VIEW] & ETF_VALID; + break; + default: + break; } - if ( !ok ) + if (!ok) { char buf[256]; - sprintf(buf,"transform_calc not valid for %d\n",state); + sprintf(buf, "transform_calc not valid for %d\n", state); os::Printer::log(buf, ELL_WARNING); } core::matrix4* matrix = Transformation[TransformationStack]; - switch ( state ) + switch (state) { - case ETS_PROJ_MODEL_VIEW: - if (flag[ETS_WORLD] & ETF_IDENTITY ) - { - matrix[state] = matrix[ETS_VIEW_PROJECTION]; - } - else - { - matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW_PROJECTION], matrix[ETS_WORLD]); - } - break; + case ETS_PROJ_MODEL_VIEW: + if (flag[ETS_WORLD] & ETF_IDENTITY) + { + matrix[state] = matrix[ETS_VIEW_PROJECTION]; + } + else + { + matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW_PROJECTION], matrix[ETS_WORLD]); + } + break; - case ETS_VIEW_PROJECTION: - matrix[state].setbyproduct_nocheck (matrix[ETS_PROJECTION], matrix[ETS_VIEW]); - break; - case ETS_MODEL_VIEW: - if ( flag[ETS_WORLD] & ETF_IDENTITY ) - { - matrix[state] = matrix[ETS_VIEW]; - } - else - { - matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW], matrix[ETS_WORLD]); - } - break; - case ETS_NORMAL: - mat44_transposed_inverse(matrix[state], matrix[ETS_MODEL_VIEW]); - break; + case ETS_VIEW_PROJECTION: + matrix[state].setbyproduct_nocheck(matrix[ETS_PROJECTION], matrix[ETS_VIEW]); + break; + case ETS_MODEL_VIEW: + if (flag[ETS_WORLD] & ETF_IDENTITY) + { + matrix[state] = matrix[ETS_VIEW]; + } + else + { + matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW], matrix[ETS_WORLD]); + } + break; + case ETS_NORMAL: + mat44_transposed_inverse(matrix[state], matrix[ETS_MODEL_VIEW]); + break; - default: - break; + default: + break; } flag[state] |= ETF_VALID; } @@ -615,18 +591,18 @@ void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core: //maybe identity (mostly for texturematrix to avoid costly multiplication) #if defined ( USE_MATRIX_TEST ) - burning_setbit( TransformationFlag[state], mat.getDefinitelyIdentityMatrix(), ETF_IDENTITY ); + burning_setbit(TransformationFlag[state], mat.getDefinitelyIdentityMatrix(), ETF_IDENTITY); #else burning_setbit(flag[state], - !memcmp(mat.pointer(), core::IdentityMatrix.pointer(),sizeof(mat)),ETF_IDENTITY + !memcmp(mat.pointer(), core::IdentityMatrix.pointer(), sizeof(mat)), ETF_IDENTITY ); #endif #if 0 - if ( changed ) + if (changed) #endif - switch ( state ) - { + switch (state) + { case ETS_PROJECTION: flag[ETS_PROJ_MODEL_VIEW] &= ~ETF_VALID; flag[ETS_VIEW_PROJECTION] &= ~ETF_VALID; @@ -658,14 +634,14 @@ void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core: #if _IRR_MATERIAL_MAX_TEXTURES_>7 case ETS_TEXTURE_7: #endif - if ( 0 == (flag[state] & ETF_IDENTITY ) ) + if (0 == (flag[state] & ETF_IDENTITY)) { EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM; } break; default: break; - } + } } @@ -678,7 +654,13 @@ const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE st bool CBurningVideoDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect* sourceRect) { +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + CNullDriver::beginScene(clearFlag & ECBF_COLOR, clearFlag & ECBF_DEPTH, clearColor, videoData, sourceRect); +#else CNullDriver::beginScene(clearFlag, clearColor, clearDepth, clearStencil, videoData, sourceRect); +#endif + + Interlaced.nr = (Interlaced.nr + 1) & interlace_control_mask; WindowId = videoData.D3D9.HWnd; SceneSourceRect = sourceRect; @@ -695,28 +677,70 @@ bool CBurningVideoDriver::endScene() return Presenter->present(BackBuffer, WindowId, SceneSourceRect); } + +//! Create render target. +IRenderTarget* CBurningVideoDriver::addRenderTarget() +{ + CSoftwareRenderTarget2* renderTarget = new CSoftwareRenderTarget2(this); + RenderTargets.push_back(renderTarget); + + return renderTarget; +} + +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) +bool CBurningVideoDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) +{ + CSoftwareRenderTarget2 target(this); + target.RenderTexture = texture; + target.TargetType = ERT_RENDER_TEXTURE; + target.Texture[0] = texture; + + if (texture) + texture->grab(); + + u16 flag = 0; + if (clearBackBuffer) flag |= ECBF_COLOR; + if (clearZBuffer) flag |= ECBF_DEPTH; + + return setRenderTargetEx(texture ? &target : 0, flag, color, 1.f, true); +} +#endif + bool CBurningVideoDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil) { +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) if (target && target->getDriverType() != EDT_BURNINGSVIDEO) { os::Printer::log("Fatal Error: Tried to set a render target not owned by this driver.", ELL_ERROR); return false; } - +#endif if (RenderTargetTexture) + { + //switching from texture to backbuffer + if (target == 0) + { + RenderTargetTexture->regenerateMipMapLevels(); + } RenderTargetTexture->drop(); + } - CSoftwareRenderTarget2* renderTarget = static_cast(target); - RenderTargetTexture = (renderTarget) ? renderTarget->getTexture() : 0; +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + RenderTargetTexture = target ? target->getTexture()[0] : 0; +#else + RenderTargetTexture = target ? ((CSoftwareRenderTarget2*)target)->Texture[0] : 0; +#endif if (RenderTargetTexture) { RenderTargetTexture->grab(); - setRenderTargetImage(((CSoftwareTexture2*)RenderTargetTexture)->getTexture()); + Interlaced.bypass = 1; + setRenderTargetImage2(((CSoftwareTexture2*)RenderTargetTexture)->getImage()); } else { - setRenderTargetImage(BackBuffer); + Interlaced.bypass = !Interlaced.enable; + setRenderTargetImage2(BackBuffer); } clearBuffers(clearFlag, clearColor, clearDepth, clearStencil); @@ -724,14 +748,18 @@ bool CBurningVideoDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag return true; } +static inline f32 map_value(f32 x, f32 in_min, f32 in_max, f32 out_min, f32 out_max) { + return (x - in_min) * (out_max - out_min) / (f32)(in_max - in_min) + out_min; +} + //! sets a render target -void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) +void CBurningVideoDriver::setRenderTargetImage2(video::IImage* color, video::IImage* depth, video::IImage* stencil) { if (RenderTargetSurface) RenderTargetSurface->drop(); core::dimension2d current = RenderTargetSize; - RenderTargetSurface = image; + RenderTargetSurface = color; RenderTargetSize.Width = 0; RenderTargetSize.Height = 0; @@ -741,6 +769,9 @@ void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) RenderTargetSize = RenderTargetSurface->getDimension(); } + RatioRenderTargetScreen.x = ScreenSize.Width ? (f32)RenderTargetSize.Width / ScreenSize.Width : 1.f; + RatioRenderTargetScreen.y = ScreenSize.Height ? (f32)RenderTargetSize.Height / ScreenSize.Height : 1.f; + int not_changed = current == RenderTargetSize; burning_setbit(TransformationFlag[0][ETS_PROJECTION], not_changed, ETF_VALID); burning_setbit(TransformationFlag[1][ETS_PROJECTION], not_changed, ETF_VALID); @@ -757,95 +788,66 @@ void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) //--------- Transform from NDC to DC, transform TexCoo ---------------------------------------------- -// controls subtexel and fill convention -#if defined(SOFTWARE_DRIVER_2_SUBTEXEL) -#define SOFTWARE_DRIVER_2_PIXEL_CENTER -0.5f -#else -#define SOFTWARE_DRIVER_2_PIXEL_CENTER -0.5f -#endif -#if 1 +//! Blur 2D Image with PixelOffset. (default 0.375f for OpenGL and Burning) +/** SideEffects: +* if IRRLICHT_2D_TEXEL_OFFSET > 0 is applied to OpenGL/Burning, Pixel-exact Texture Coordinates do not match. +* Currently Version 1.8,1.9 has that in the Irrlicht 2D Examples where you get a Magenta Border on the Sprites +* and in the draw2DImage4cFilter Tests +*/ +#define IRRLICHT_2D_TEXEL_OFFSET 0.f + + +//--------- Transform from NDC to DC ---------------------------------------------- + +// used to scale <-1,-1><1,1> to viewport [center,scale] +// controls subtexel and fill convention. +// Don't tweak SOFTWARE_DRIVER_2_SUBTEXEL (-0.5f in m[1]) anymore to control texture blur effect, it's used for viewport scaling. +// naming is misleading. it will write outside memory location.. -// used to scale <-1,-1><1,1> to viewport void buildNDCToDCMatrix(f32* m, const core::rect& viewport, f32 tx) { - m[0] = (viewport.getWidth() + tx) * 0.5f; - m[1] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ((viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X) * 0.5f); + m[0] = (viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X + tx) * 0.5f; + m[1] = (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X-1) * 0.5f; - m[2] = (viewport.getHeight() + tx) * -0.5f; - m[3] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ((viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y) * 0.5f); + m[2] = (viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y + tx) * -0.5f; + m[3] = (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y-1) * 0.5f; } -#else -// used to scale <-1,-1><1,1> to viewport -void buildNDCToDCMatrix( core::matrix4& out, const core::rect& viewport) -{ - //guard band to stay in screen bounds.(empirical). get holes left side otherwise or out of screen - //TODO: match openGL or D3D. - //assumption pixel center, top-left rule and rounding error projection deny exact match without additional clipping - //or triangle render scanline doesn't step on correct texel center - //or sampler is not on texel center - - f32* m = out.pointer(); -#if defined(Tweak_Burning) && 0 - m[0] = (viewport.getWidth() + Tweak.ndc_shrink_x ) * Tweak.ndc_scale_x; - m[5] = (viewport.getHeight() + Tweak.ndc_shrink_y ) * Tweak.ndc_scale_y; - m[12] = Tweak.ndc_trans_x + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); - m[13] = Tweak.ndc_trans_y + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); -#endif - - m[0] = (viewport.getWidth() - 0.75f ) * 0.5f; - m[1] = 0.f; - m[2] = 0.f; - m[3] = 0.f; - m[4] = 0.f; - m[5] = (viewport.getHeight() - 0.75f ) * -0.5f; - m[6] = 0.f; - m[7] = 0.f; - m[8] = 0.f; - m[9] = 0.f; - m[10] = 1.f; - m[11] = 0.f; - m[12] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); - m[13] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); - m[14] = 0.f; - m[15] = 1.f; -} -#endif - - -//--------- Transform from NCD to DC ---------------------------------------------- //! sets a viewport void CBurningVideoDriver::setViewPort(const core::rect& area) { ViewPort = area; - core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); + core::rect rendert(0, 0, RenderTargetSize.Width, RenderTargetSize.Height); ViewPort.clipAgainst(rendert); - buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[0], ViewPort,-0.375f); - buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[1], ViewPort, 0.f); // OverrideMaterial2DEnabled ? -0.375f : 0.f); + buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[0], ViewPort, 1.f/2048.f); //SkyBox,Billboard 90° problem + buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[1], ViewPort, 0.f); // OverrideMaterial2DEnabled ? -IRRLICHT_2D_TEXEL_OFFSET : 0.f); if (CurrentShader) - CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort, Interlaced); } void CBurningVideoDriver::setScissor(int x, int y, int width, int height) { - AbsRectangle v0; - v0.x0 = x; - v0.y0 = y; - v0.x1 = x+width; - v0.y1 = y+width; + //openGL + //y = rt.Height - y - height; + + //coming from GUI + AbsRectangle v0; + v0.x0 = core::floor32(x * RatioRenderTargetScreen.x); + v0.y0 = core::floor32(y * RatioRenderTargetScreen.y); + v0.x1 = core::floor32((x + width) * RatioRenderTargetScreen.x); + v0.y1 = core::floor32((y + height) * RatioRenderTargetScreen.y); - const core::dimension2d& rt = getCurrentRenderTargetSize(); AbsRectangle v1; v1.x0 = 0; v1.y0 = 0; - v1.x1 = rt.Width; - v1.y1 = rt.Height; + v1.x1 = RenderTargetSize.Width; + v1.y1 = RenderTargetSize.Height; intersect(Scissor, v0, v1); } @@ -858,14 +860,14 @@ void CBurningVideoDriver::setScissor(int x, int y, int width, int height) cam is (0,0,-1) */ -const sVec4 CBurningVideoDriver::NDCPlane[6+2] = +const sVec4 CBurningVideoDriver::NDCPlane[6 + 2] = { - sVec4( 0.f, 0.f, -1.f, -1.f ), // near - sVec4( 0.f, 0.f, 1.f, -1.f ), // far - sVec4( 1.f, 0.f, 0.f, -1.f ), // left - sVec4( -1.f, 0.f, 0.f, -1.f ), // right - sVec4( 0.f, 1.f, 0.f, -1.f ), // bottom - sVec4( 0.f, -1.f, 0.f, -1.f ) // top + sVec4(0.f, 0.f, -1.f, -1.f), // near + sVec4(0.f, 0.f, 1.f, -1.f), // far + sVec4(1.f, 0.f, 0.f, -1.f), // left + sVec4(-1.f, 0.f, 0.f, -1.f), // right + sVec4(0.f, 1.f, 0.f, -1.f), // bottom + sVec4(0.f, -1.f, 0.f, -1.f) // top }; @@ -892,80 +894,80 @@ const sVec4 CBurningVideoDriver::NDCPlane[6+2] = */ #ifdef IRRLICHT_FAST_MATH -REALINLINE size_t CBurningVideoDriver::clipToFrustumTest ( const s4DVertex* v ) const +REALINLINE size_t CBurningVideoDriver::clipToFrustumTest(const s4DVertex* v) const { size_t flag; f32 test[8]; - const f32 w = - v->Pos.w; + const f32 w = -v->Pos.w; // a conditional move is needed....FCOMI ( but we don't have it ) // so let the fpu calculate and write it back. // cpu makes the compare, interleaving - test[0] = v->Pos.z + w; + test[0] = v->Pos.z + w; test[1] = -v->Pos.z + w; - test[2] = v->Pos.x + w; + test[2] = v->Pos.x + w; test[3] = -v->Pos.x + w; - test[4] = v->Pos.y + w; + test[4] = v->Pos.y + w; test[5] = -v->Pos.y + w; const u32* a = F32_AS_U32_POINTER(test); - flag = (a[0] ) >> 31; + flag = (a[0]) >> 31; flag |= (a[1] & 0x80000000) >> 30; flag |= (a[2] & 0x80000000) >> 29; flag |= (a[3] & 0x80000000) >> 28; flag |= (a[4] & 0x80000000) >> 27; flag |= (a[5] & 0x80000000) >> 26; -/* - flag = (IR ( test[0] ) ) >> 31; - flag |= (IR ( test[1] ) & 0x80000000 ) >> 30; - flag |= (IR ( test[2] ) & 0x80000000 ) >> 29; - flag |= (IR ( test[3] ) & 0x80000000 ) >> 28; - flag |= (IR ( test[4] ) & 0x80000000 ) >> 27; - flag |= (IR ( test[5] ) & 0x80000000 ) >> 26; -*/ -/* - flag = F32_LOWER_EQUAL_0 ( test[0] ); - flag |= F32_LOWER_EQUAL_0 ( test[1] ) << 1; - flag |= F32_LOWER_EQUAL_0 ( test[2] ) << 2; - flag |= F32_LOWER_EQUAL_0 ( test[3] ) << 3; - flag |= F32_LOWER_EQUAL_0 ( test[4] ) << 4; - flag |= F32_LOWER_EQUAL_0 ( test[5] ) << 5; -*/ + /* + flag = (IR ( test[0] ) ) >> 31; + flag |= (IR ( test[1] ) & 0x80000000 ) >> 30; + flag |= (IR ( test[2] ) & 0x80000000 ) >> 29; + flag |= (IR ( test[3] ) & 0x80000000 ) >> 28; + flag |= (IR ( test[4] ) & 0x80000000 ) >> 27; + flag |= (IR ( test[5] ) & 0x80000000 ) >> 26; + */ + /* + flag = F32_LOWER_EQUAL_0 ( test[0] ); + flag |= F32_LOWER_EQUAL_0 ( test[1] ) << 1; + flag |= F32_LOWER_EQUAL_0 ( test[2] ) << 2; + flag |= F32_LOWER_EQUAL_0 ( test[3] ) << 3; + flag |= F32_LOWER_EQUAL_0 ( test[4] ) << 4; + flag |= F32_LOWER_EQUAL_0 ( test[5] ) << 5; + */ return flag; } #else -REALINLINE size_t clipToFrustumTest ( const s4DVertex* v ) +REALINLINE size_t clipToFrustumTest(const s4DVertex* v) { size_t flag = 0; - flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0; - flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0; + flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0; + flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0; - flag |= v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_LEFT : 0; - flag |= -v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_RIGHT : 0; + flag |= v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_LEFT : 0; + flag |= -v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_RIGHT : 0; - flag |= v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_BOTTOM : 0; - flag |= -v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_TOP : 0; + flag |= v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_BOTTOM : 0; + flag |= -v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_TOP : 0; -/* - for ( u32 i = 0; i <= 6; ++i ) - { - if (v->Pos.dot_xyzw(NDCPlane[i]) <= 0.f) flag |= ((size_t)1) << i; - } -*/ + /* + for ( u32 i = 0; i <= 6; ++i ) + { + if (v->Pos.dot_xyzw(NDCPlane[i]) <= 0.f) flag |= ((size_t)1) << i; + } + */ return flag; } #endif // _MSC_VER -size_t clipToHyperPlane ( +size_t clipToHyperPlane( s4DVertexPair* burning_restrict dest, const s4DVertexPair* burning_restrict source, const size_t inCount, @@ -979,39 +981,39 @@ size_t clipToHyperPlane ( const s4DVertex* b = source; ipoltype bDotPlane; - bDotPlane = b->Pos.dot_xyzw( plane ); + bDotPlane = b->Pos.dot_xyzw(plane); -/* - for( u32 i = 1; i < inCount + 1; ++i) - { -#if 0 - a = source + (i%inCount)*2; -#else - const s32 condition = i - inCount; - const s32 index = (( ( condition >> 31 ) & ( i ^ condition ) ) ^ condition ) << 1; - a = source + index; -#endif -*/ + /* + for( u32 i = 1; i < inCount + 1; ++i) + { + #if 0 + a = source + (i%inCount)*2; + #else + const s32 condition = i - inCount; + const s32 index = (( ( condition >> 31 ) & ( i ^ condition ) ) ^ condition ) << 1; + a = source + index; + #endif + */ //Sutherland–Hodgman - for(size_t i = 0; i < inCount; ++i) + for (size_t i = 0; i < inCount; ++i) { - a = source + (i == inCount-1 ? 0 : s4DVertex_ofs(i+1)); + a = source + (i == inCount - 1 ? 0 : s4DVertex_ofs(i + 1)); // current point inside - if (ipol_lower_equal_0(a->Pos.dot_xyzw( plane )) ) + if (ipol_lower_equal_0(a->Pos.dot_xyzw(plane))) { // last point outside - if (ipol_greater_0( bDotPlane ) ) + if (ipol_greater_0(bDotPlane)) { // intersect line segment with plane - out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane) ); + out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane)); out += sizeof_s4DVertexPairRel; outCount += 1; } // copy current to out //*out = *a; - memcpy_s4DVertexPair( out, a); + memcpy_s4DVertexPair(out, a); b = out; out += sizeof_s4DVertexPairRel; @@ -1020,11 +1022,11 @@ size_t clipToHyperPlane ( else { // current point outside - if (ipol_lower_equal_0( bDotPlane ) ) + if (ipol_lower_equal_0(bDotPlane)) { // previous was inside // intersect line segment with plane - out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane) ); + out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane)); out += sizeof_s4DVertexPairRel; outCount += 1; } @@ -1032,7 +1034,7 @@ size_t clipToHyperPlane ( b = a; } - bDotPlane = b->Pos.dot_xyzw( plane ); + bDotPlane = b->Pos.dot_xyzw(plane); } return outCount; @@ -1043,7 +1045,7 @@ size_t clipToHyperPlane ( Clip on all planes. Clipper.data clipmask per face */ -size_t CBurningVideoDriver::clipToFrustum(const size_t vIn /*, const size_t clipmask_for_face*/ ) +size_t CBurningVideoDriver::clipToFrustum(const size_t vIn /*, const size_t clipmask_for_face*/) { s4DVertexPair* v0 = Clipper.data; s4DVertexPair* v1 = Clipper_temp.data; @@ -1065,7 +1067,7 @@ size_t CBurningVideoDriver::clipToFrustum(const size_t vIn /*, const size_t clip //clipMask checked outside - always clip all planes #if 0 - if (0 == (clipMask & ((size_t)1< 0 dest[g].Tex[0] = source[g].Tex[0]; @@ -1147,34 +1149,34 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project (s4DVertexPair* dest,const #endif #if BURNING_MATERIAL_MAX_COLORS > 0 - #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - dest[g].Color[0] = source[g].Color[0] * iw; // alpha? - #else - dest[g].Color[0] = source[g].Color[0]; - #endif +#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + dest[g].Color[0] = source[g].Color[0] * iw; // alpha? +#else + dest[g].Color[0] = source[g].Color[0]; +#endif #endif #if BURNING_MATERIAL_MAX_COLORS > 1 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - dest[g].Color[1] = source[g].Color[1] * iw; // alpha? + dest[g].Color[1] = source[g].Color[1] * iw; // alpha? #else - dest[g].Color[1] = source[g].Color[1]; + dest[g].Color[1] = source[g].Color[1]; #endif #endif #if BURNING_MATERIAL_MAX_COLORS > 2 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - dest[g].Color[2] = source[g].Color[2] * iw; // alpha? + dest[g].Color[2] = source[g].Color[2] * iw; // alpha? #else - dest[g].Color[2] = source[g].Color[2]; + dest[g].Color[2] = source[g].Color[2]; #endif #endif #if BURNING_MATERIAL_MAX_COLORS > 3 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - dest[g].Color[3] = source[g].Color[3] * iw; // alpha? + dest[g].Color[3] = source[g].Color[3] * iw; // alpha? #else - dest[g].Color[3] = source[g].Color[3]; + dest[g].Color[3] = source[g].Color[3]; #endif #endif @@ -1187,24 +1189,25 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project (s4DVertexPair* dest,const +#if 0 /*! crossproduct in projected 2D, face */ -REALINLINE f32 CBurningVideoDriver::screenarea_inside(const s4DVertexPair* burning_restrict const face[] ) const +REALINLINE f32 CBurningVideoDriver::screenarea_inside(const s4DVertexPair* burning_restrict const face[]) const { - return ( ((face[1]+1)->Pos.x - (face[0]+1)->Pos.x) * ((face[2]+1)->Pos.y - (face[0]+1)->Pos.y) ) - - ( ((face[2]+1)->Pos.x - (face[0]+1)->Pos.x) * ((face[1]+1)->Pos.y - (face[0]+1)->Pos.y) ); -/* - float signedArea = 0; - for (int k = 1; k < output->count; k++) { - signedArea += (output->vertices[k - 1].values[0] * output->vertices[k - 0].values[1]); - signedArea -= (output->vertices[k - 0].values[0] * output->vertices[k - 1].values[1]); - } -*/ + return (((face[1] + 1)->Pos.x - (face[0] + 1)->Pos.x) * ((face[2] + 1)->Pos.y - (face[0] + 1)->Pos.y)) - + (((face[2] + 1)->Pos.x - (face[0] + 1)->Pos.x) * ((face[1] + 1)->Pos.y - (face[0] + 1)->Pos.y)); + /* + float signedArea = 0; + for (int k = 1; k < output->count; k++) { + signedArea += (output->vertices[k - 1].values[0] * output->vertices[k - 0].values[1]); + signedArea -= (output->vertices[k - 0].values[0] * output->vertices[k - 1].values[1]); + } + */ } -#if 0 -static inline f32 dot(const sVec2& a,const sVec2& b) { return a.x * b.x + a.y * b.y; } + +static inline f32 dot(const sVec2& a, const sVec2& b) { return a.x * b.x + a.y * b.y; } sVec2 dFdx(const sVec2& v) { return v; } sVec2 dFdy(const sVec2& v) { return v; } @@ -1217,7 +1220,8 @@ f32 MipmapLevel(const sVec2& uv, const sVec2& textureSize) } #endif -#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( (u32)tex ) ) +//#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( (u32)tex ) ) +#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.TextureLayer[tex].Texture ) /*! calculate from unprojected. @@ -1227,7 +1231,7 @@ f32 MipmapLevel(const sVec2& uv, const sVec2& textureSize) Atlas problem */ REALINLINE s32 CBurningVideoDriver::lodFactor_inside(const s4DVertexPair* burning_restrict const face[], - const size_t m, f32 dc_area, f32 lod_bias) const + const size_t m, const f32 dc_area, const f32 lod_bias) const { /* sVec2 a(v[1]->Tex[tex].x - v[0]->Tex[tex].x,v[1]->Tex[tex].y - v[0]->Tex[tex].y); @@ -1257,7 +1261,7 @@ REALINLINE s32 CBurningVideoDriver::lodFactor_inside(const s4DVertexPair* burnin // - ((face[2]->Tex[m].x - face[0]->Tex[m].x) * (face[1]->Tex[m].y - face[0]->Tex[m].y)); //if (signedArea*signedArea <= 0.00000000001f) - if (signedArea.fields.exp == 0 ) + if (signedArea.fields.exp == 0) { ieee754 _max; _max.u = t[0].abs.frac_exp; @@ -1267,23 +1271,25 @@ REALINLINE s32 CBurningVideoDriver::lodFactor_inside(const s4DVertexPair* burnin signedArea.u = _max.fields.exp ? _max.u : ieee754_one; -/* - //dot,length - ieee754 v[2]; - v[0].f = t[0] * t[2]; - v[1].f = t[1] * t[3]; + /* + //dot,length + ieee754 v[2]; + v[0].f = t[0] * t[2]; + v[1].f = t[1] * t[3]; - //signedArea.f = t[4] > t[5] ? t[4] : t[5]; - signedArea.u = v[0].fields.frac > v[1].fields.frac ? v[0].u : v[1].u; - if (signedArea.fields.exp == 0) - { - return -1; - } -*/ + //signedArea.f = t[4] > t[5] ? t[4] : t[5]; + signedArea.u = v[0].fields.frac > v[1].fields.frac ? v[0].u : v[1].u; + if (signedArea.fields.exp == 0) + { + return -1; + } + */ } //only guessing: take more detail (lower mipmap) in light+bump textures //assume transparent add is ~50% transparent -> more detail + + // 2.f from dc_area, 2.f from tex triangle ( parallelogram area) const u32* d = MAT_TEXTURE(m)->getMipMap0_Area(); f32 texelspace = d[0] * d[1] * lod_bias; //(m ? 0.5f : 0.5f); @@ -1292,20 +1298,8 @@ REALINLINE s32 CBurningVideoDriver::lodFactor_inside(const s4DVertexPair* burnin ratio.fields.sign = 0; //log2(0)==denormal [ use high lod] [ only if dc_area == 0 checked outside ] -#if 0 - if (ratio.fields.exp == 0) - { - int g = 1; - } -#endif - //log2 return (ratio.fields.exp & 0x80) ? ratio.fields.exp - 127 : 0; /*denormal very high lod*/ - //return (ratio.f <= 1.f) ? 0 : 1; - //f32 texArea = MAT_TEXTURE(m)->getLODFactor(signedArea); // texelarea_inside(face, m); - //s32 lodFactor = s32_log2_f32(texArea * dc_area); /* avoid denorm */ - - //return MAT_TEXTURE(m)->getLODFactor(signedArea); } @@ -1357,15 +1351,15 @@ void CBurningVideoDriver::VertexCache_map_source_format() u32 s0 = sizeof(s4DVertex); u32 s1 = sizeof(s4DVertex_proxy); - if ( s1 <= sizeof_s4DVertex /2 ) + if (s1 <= sizeof_s4DVertex / 2) { - os::Printer::log ( "BurningVideo vertex format unnecessary to large", ELL_WARNING ); + os::Printer::log("BurningVideo vertex format unnecessary to large", ELL_WARNING); } //memcpy_vertex - if ( s0 != sizeof_s4DVertex || ((sizeof_s4DVertex * sizeof_s4DVertexPairRel)&31)) + if (s0 != sizeof_s4DVertex || ((sizeof_s4DVertex * sizeof_s4DVertexPairRel) & 31)) { - os::Printer::log ( "BurningVideo vertex format compile problem", ELL_ERROR ); + os::Printer::log("BurningVideo vertex format compile problem", ELL_ERROR); _IRR_DEBUG_BREAK_IF(1); } @@ -1377,6 +1371,13 @@ void CBurningVideoDriver::VertexCache_map_source_format() } #endif + if (((unsigned long long)Transformation&15) || ((unsigned long long)TransformationFlag & 15)) + { + os::Printer::log("BurningVideo Matrix Stack not 16 byte aligned", ELL_ERROR); + _IRR_DEBUG_BREAK_IF(1); + } + + SVSize* vSize = VertexCache.vSize; //vSize[E4VT_STANDARD].Format = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_LIGHT_1 | VERTEX4D_FORMAT_SPECULAR; vSize[E4VT_STANDARD].Format = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_2_FOG; @@ -1420,30 +1421,30 @@ void CBurningVideoDriver::VertexCache_map_source_format() vSize[E4VT_LINE].TexCooSize = 0; size_t size; - for ( size_t i = 0; i < E4VT_COUNT; ++i ) + for (size_t i = 0; i < E4VT_COUNT; ++i) { size_t& flag = vSize[i].Format; #if !defined(SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR) flag &= ~VERTEX4D_FORMAT_SPECULAR; #endif - if ( vSize[i].TexSize > BURNING_MATERIAL_MAX_TEXTURES ) + if (vSize[i].TexSize > BURNING_MATERIAL_MAX_TEXTURES) vSize[i].TexSize = BURNING_MATERIAL_MAX_TEXTURES; size = (flag & VERTEX4D_FORMAT_MASK_TEXTURE) >> 16; - if ( size > BURNING_MATERIAL_MAX_TEXTURES ) + if (size > BURNING_MATERIAL_MAX_TEXTURES) { flag = (flag & ~VERTEX4D_FORMAT_MASK_TEXTURE) | (BURNING_MATERIAL_MAX_TEXTURES << 16); } size = (flag & VERTEX4D_FORMAT_MASK_COLOR) >> 20; - if ( size > BURNING_MATERIAL_MAX_COLORS ) + if (size > BURNING_MATERIAL_MAX_COLORS) { flag = (flag & ~VERTEX4D_FORMAT_MASK_COLOR) | (BURNING_MATERIAL_MAX_COLORS << 20); } size = (flag & VERTEX4D_FORMAT_MASK_LIGHT) >> 24; - if ( size > BURNING_MATERIAL_MAX_LIGHT_TANGENT) + if (size > BURNING_MATERIAL_MAX_LIGHT_TANGENT) { flag = (flag & ~VERTEX4D_FORMAT_MASK_LIGHT) | (BURNING_MATERIAL_MAX_LIGHT_TANGENT << 24); } @@ -1461,8 +1462,6 @@ void CBurningVideoDriver::VertexCache_map_source_format() Material.resetRenderStates = true; Material.Fallback_MaterialType = EMT_SOLID; - - } @@ -1476,15 +1475,15 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest u8* burning_restrict source; s4DVertex* burning_restrict dest; - source = (u8*) VertexCache.vertices + ( sourceIndex * VertexCache.vSize[VertexCache.vType].Pitch ); + source = (u8*)VertexCache.vertices + (sourceIndex * VertexCache.vSize[VertexCache.vType].Pitch); // it's a look ahead so we never hit it.. // but give priority... //VertexCache.info[ destIndex ].hit = hitCount; // store info - VertexCache.info[ destIndex ].index = sourceIndex; - VertexCache.info[ destIndex ].hit = 0; + VertexCache.info[destIndex].index = sourceIndex; + VertexCache.info[destIndex].hit = 0; // destination Vertex dest = VertexCache.mem.data + s4DVertex_ofs(destIndex); @@ -1520,12 +1519,12 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest #if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) // vertex, normal in light(eye) space - if ( Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM|TL_FOG)) ) + if (Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM | TL_FOG))) { sVec4 vertex4; //eye coordinate position of vertex - matrix[ETS_MODEL_VIEW].transformVect ( &vertex4.x, base->Pos ); + matrix[ETS_MODEL_VIEW].transformVect(&vertex4.x, base->Pos); - f32 iw = reciprocal_zero(vertex4.w); + const f32 iw = reciprocal_zero(vertex4.w); EyeSpace.vertex.x = vertex4.x * iw; EyeSpace.vertex.y = vertex4.y * iw; EyeSpace.vertex.z = vertex4.z * iw; @@ -1572,23 +1571,23 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest #if BURNING_MATERIAL_MAX_COLORS > 0 -// apply lighting model + // apply lighting model #if defined (SOFTWARE_DRIVER_2_LIGHTING) - if ( Material.org.Lighting ) + if (Material.org.Lighting) { - lightVertex_eye ( dest, base->Color.color ); + lightVertex_eye(dest, base->Color.color); } else { - dest->Color[0].setA8R8G8B8 ( base->Color.color ); + dest->Color[0].setA8R8G8B8(base->Color.color); } #else - dest->Color[0].setA8R8G8B8 ( base->Color.color ); + dest->Color[0].setA8R8G8B8(base->Color.color); #endif #endif //vertex fog - if (EyeSpace.TL_Flag & TL_FOG ) //Material.org.FogEnable + if (EyeSpace.TL_Flag & TL_FOG) //Material.org.FogEnable { f32 fog_factor = 1.f; @@ -1611,230 +1610,151 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest } sVec4* a = dest->Color + ((VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_COLOR_2_FOG) ? 1 : 0); - a->a = core::clamp(fog_factor, 0.f, 1.f); + a->a = clampf01(fog_factor); } - // Texture Transform -#if defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) - - if ( 0 == (EyeSpace.TL_Flag & TL_TEXTURE_TRANSFORM) ) -#endif // SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + // Texture Coo Transform + // Always set all internal uv (v1.9 SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM always on) + for (size_t t = 0; t < BURNING_MATERIAL_MAX_TEXTURES; ++t) { - // Irrlicht TCoords and TCoords2 must be contiguous memory. baseTCoord has no 4 byte aligned start address! - const f32* baseTCoord = &base->TCoords.X; - - switch (VertexCache.vSize[VertexCache.vType].TexCooSize) - { -#if BURNING_MATERIAL_MAX_TEXTURES == 4 - case 0: - dest->Tex[0].x = 0.f; - dest->Tex[0].y = 0.f; - dest->Tex[1].x = 0.f; - dest->Tex[1].y = 0.f; - dest->Tex[2].x = 0.f; - dest->Tex[2].y = 0.f; - dest->Tex[3].x = 0.f; - dest->Tex[3].y = 0.f; - break; - case 1: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = 0.f; - dest->Tex[1].y = 0.f; - dest->Tex[2].x = 0.f; - dest->Tex[2].y = 0.f; - dest->Tex[3].x = 0.f; - dest->Tex[3].y = 0.f; - break; - case 2: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = baseTCoord[2]; - dest->Tex[1].y = baseTCoord[3]; - dest->Tex[2].x = 0.f; - dest->Tex[2].y = 0.f; - dest->Tex[3].x = 0.f; - dest->Tex[3].y = 0.f; - break; - case 3: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = baseTCoord[2]; - dest->Tex[1].y = baseTCoord[3]; - dest->Tex[2].x = baseTCoord[4]; - dest->Tex[2].y = baseTCoord[5]; - dest->Tex[3].x = 0.f; - dest->Tex[3].y = 0.f; - break; - case 4: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = baseTCoord[2]; - dest->Tex[1].y = baseTCoord[3]; - dest->Tex[2].x = baseTCoord[4]; - dest->Tex[2].y = baseTCoord[5]; - dest->Tex[3].x = baseTCoord[6]; - dest->Tex[3].y = baseTCoord[7]; - break; -#endif - -#if BURNING_MATERIAL_MAX_TEXTURES == 2 - case 0: - dest->Tex[0].x = 0.f; - dest->Tex[0].y = 0.f; - dest->Tex[1].x = 0.f; - dest->Tex[1].y = 0.f; - break; - - case 1: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = 0.f; - dest->Tex[1].y = 0.f; - break; - case 2: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - dest->Tex[1].x = baseTCoord[2]; - dest->Tex[1].y = baseTCoord[3]; - break; -#endif -#if BURNING_MATERIAL_MAX_TEXTURES == 1 - case 0: - dest->Tex[0].x = 0.f; - dest->Tex[0].y = 0.f; - break; - case 1: - dest->Tex[0].x = baseTCoord[0]; - dest->Tex[0].y = baseTCoord[1]; - break; -#endif - default: - break; - } - } -#if defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) - else - { - /* - Generate texture coordinates as linear functions so that: - u = Ux*x + Uy*y + Uz*z + Uw - v = Vx*x + Vy*y + Vz*z + Vw - The matrix M for this case is: - Ux Vx 0 0 - Uy Vy 0 0 - Uz Vz 0 0 - Uw Vw 0 0 - */ - - const sVec4& u = EyeSpace.cam_dir; // EyeSpace.vertex.normalized - const sVec4& n = EyeSpace.normal; sVec4 r; + f32 tx, ty; - const size_t* flag = TransformationFlag[TransformationStack]; - for ( u32 t = 0; t != VertexCache.vSize[VertexCache.vType].TexSize; ++t ) + // texgen + const size_t flag = TransformationFlag[TransformationStack][ETS_TEXTURE_0 + t]; + if (flag & ETF_TEXGEN_CAMERA_SPHERE) { - // texgen - if (flag[ETS_TEXTURE_0+t] & ETF_TEXGEN_CAMERA_SPHERE ) - { - //reflect(u,N) u - 2.0 * dot(N, u) * N - // cam is (0,0,-1), tex flipped - f32 dot = -2.f * n.dot_xyz(u); - r.x = u.x + dot * n.x; - r.y = u.y + dot * n.y; - r.z = u.z + dot * n.z; + //reflect(u,N) u - 2.0 * dot(N, u) * N + // cam is (0,0,-1), tex flipped - //openGL - f32 m = 2.f * sqrtf(r.x*r.x+r.y*r.y+(r.z+1.f)*(r.z+1.f)); - dest[0].Tex[t].x = r.x / m + 0.5f; - dest[0].Tex[t].y = -r.y / m + 0.5f; + const sVec4& u = EyeSpace.cam_dir; // EyeSpace.vertex.normalized + const sVec4& n = EyeSpace.normal; -/* - //~d3d with spheremap scale - f32 m = 0.25f / (0.00001f + sqrtf(r.x*r.x+r.y*r.y+r.z*r.z)); - dest[0].Tex[t].x = r.x * m + 0.5f; - dest[0].Tex[t].y = -r.y * m + 0.5f; -*/ - } - else if (flag[ETS_TEXTURE_0+t] & ETF_TEXGEN_CAMERA_REFLECTION ) - { - //reflect(u,N) u - 2.0 * dot(N, u) * N - // cam is (0,0,-1), tex flipped - f32 dot = -2.f * n.dot_xyz(u); - r.x = u.x + dot * n.x; - r.y = u.y + dot * n.y; - r.z = u.z + dot * n.z; + f32 dot = -2.f * n.dot_xyz(u); + r.x = u.x + dot * n.x; + r.y = u.y + dot * n.y; + r.z = u.z + dot * n.z; - //openGL - dest[0].Tex[t].x = r.x; - dest[0].Tex[t].y = -r.y; -/* + //openGL + f32 m = 2.f * sqrtf(r.x * r.x + r.y * r.y + (r.z + 1.f) * (r.z + 1.f)); + tx = r.x / m + 0.5f; + ty = -r.y / m + 0.5f; + + /* + //~d3d with spheremap scale + f32 m = 0.25f / (0.00001f + sqrtf(r.x*r.x+r.y*r.y+r.z*r.z)); + dest[0].Tex[t].x = r.x * m + 0.5f; + dest[0].Tex[t].y = -r.y * m + 0.5f; + */ + } + else if (flag & ETF_TEXGEN_CAMERA_REFLECTION) + { + //reflect(u,N) u - 2.0 * dot(N, u) * N + // cam is (0,0,-1), tex flipped + + const sVec4& u = EyeSpace.cam_dir; // EyeSpace.vertex.normalized + const sVec4& n = EyeSpace.normal; + + f32 dot = -2.f * n.dot_xyz(u); + r.x = u.x + dot * n.x; + r.y = u.y + dot * n.y; + r.z = u.z + dot * n.z; + + //openGL + tx = r.x; + ty = -r.y; + /* //~d3d with spheremap scale dest[0].Tex[t].x = r.x; dest[0].Tex[t].y = r.y; -*/ - } - else if (VertexCache.vSize[VertexCache.vType].TexCooSize > t) - { - const f32* M = matrix[ETS_TEXTURE_0 + t].pointer(); - - // Irrlicht TCoords and TCoords2 must be contiguous memory. baseTCoord has no 4 byte aligned start address! - const f32* baseTCoord = &base->TCoords.X; - - sVec4 srcT; - srcT.x = baseTCoord[(t * 2) + 0]; - srcT.y = baseTCoord[(t * 2) + 1]; - - switch ( Material.org.TextureLayer[t].TextureWrapU ) - { - case ETC_CLAMP: - case ETC_CLAMP_TO_EDGE: - case ETC_CLAMP_TO_BORDER: - dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); - break; - case ETC_MIRROR: - dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; - if (core::fract(dest->Tex[t].x)>0.5f) - dest->Tex[t].x=1.f-dest->Tex[t].x; - break; - case ETC_MIRROR_CLAMP: - case ETC_MIRROR_CLAMP_TO_EDGE: - case ETC_MIRROR_CLAMP_TO_BORDER: - dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); - if (core::fract(dest->Tex[t].x)>0.5f) - dest->Tex[t].x=1.f-dest->Tex[t].x; - break; - case ETC_REPEAT: - default: - dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; - break; - } - switch ( Material.org.TextureLayer[t].TextureWrapV ) - { - case ETC_CLAMP: - case ETC_CLAMP_TO_EDGE: - case ETC_CLAMP_TO_BORDER: - dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); - break; - case ETC_MIRROR: - dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; - if (core::fract(dest->Tex[t].y)>0.5f) - dest->Tex[t].y=1.f-dest->Tex[t].y; - break; - case ETC_MIRROR_CLAMP: - case ETC_MIRROR_CLAMP_TO_EDGE: - case ETC_MIRROR_CLAMP_TO_BORDER: - dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); - if (core::fract(dest->Tex[t].y)>0.5f) - dest->Tex[t].y=1.f-dest->Tex[t].y; - break; - case ETC_REPEAT: - default: - dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; - break; - } - } + */ } + else + if (t < VertexCache.vSize[VertexCache.vType].TexCooSize) + { + // Irrlicht TCoords and TCoords2 must be contiguous memory. baseTCoord has no 4 byte aligned start address! + const sVec2Pack* baseTCoord = (const sVec2Pack*)&base->TCoords.X; + + tx = baseTCoord[t].x; + ty = baseTCoord[t].y; + } + else + { + tx = 0.f; + ty = 0.f; + } + + //transform + if (!(flag & ETF_IDENTITY)) + { + /* + Generate texture coordinates as linear functions so that: + u = Ux*x + Uy*y + Uz*z + Uw + v = Vx*x + Vy*y + Vz*z + Vw + The matrix M for this case is: + Ux Vx 0 0 + Uy Vy 0 0 + Uz Vz 0 0 + Uw Vw 0 0 + */ + + const f32* M = matrix[ETS_TEXTURE_0 + t].pointer(); + + f32 _tx = tx; + f32 _ty = ty; + tx = M[0] * _tx + M[4] * _ty + M[8]; + ty = M[1] * _tx + M[5] * _ty + M[9]; + } + + switch (Material.org.TextureLayer[t].TextureWrapU) + { + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + tx = clampf01(tx); + break; + case ETC_MIRROR: + if (core::fract(tx) > 0.5f) + tx = 1.f - tx; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + tx = clampf01(tx); + if (core::fract(tx) > 0.5f) + tx = 1.f - tx; + break; + case ETC_REPEAT: + // texel access is always modulo + default: + break; + } + switch (Material.org.TextureLayer[t].TextureWrapV) + { + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + ty = clampf01(ty); + break; + case ETC_MIRROR: + if (core::fract(ty) > 0.5f) + ty = 1.f - ty; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + ty = clampf01(ty); + if (core::fract(ty) > 0.5f) + ty = 1.f - ty; + break; + case ETC_REPEAT: + // texel access is always modulo + default: + break; + } + + dest->Tex[t].x = tx; + dest->Tex[t].y = ty; } @@ -1843,7 +1763,7 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest ((VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_MASK_TANGENT) == VERTEX4D_FORMAT_BUMP_DOT3) ) { - const S3DVertexTangents *tangent = ((S3DVertexTangents*) source ); + const S3DVertexTangents* tangent = ((S3DVertexTangents*)source); sVec4 vp; sVec4 light_accu; @@ -1851,10 +1771,10 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest light_accu.y = 0.f; light_accu.z = 0.f; light_accu.w = 0.f; - for ( u32 i = 0; i < 2 && i < EyeSpace.Light.size (); ++i ) + for (u32 i = 0; i < 2 && i < EyeSpace.Light.size(); ++i) { - const SBurningShaderLight &light = EyeSpace.Light[i]; - if ( !light.LightIsOn ) + const SBurningShaderLight& light = EyeSpace.Light[i]; + if (!light.LightIsOn) continue; // lightcolor with standard model @@ -1870,12 +1790,12 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest #endif // transform by tangent matrix - light_accu.x += (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z ); - light_accu.y += (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z ); - light_accu.z += (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z ); + light_accu.x += (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z); + light_accu.y += (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z); + light_accu.z += (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z); } //normalize [-1,+1] to [0,1] -> obsolete - light_accu.normalize_pack_xyz(dest->LightTangent[0],1.f, 0.f); + light_accu.normalize_pack_xyz(dest->LightTangent[0], 1.f, 0.f); dest->Tex[1].x = dest->Tex[0].x; dest->Tex[1].y = dest->Tex[0].y; @@ -1888,29 +1808,29 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest } #endif //if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 -#endif // SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM +//#endif // SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM clipandproject: // test vertex visible - dest[0].flag = (u32) (clipToFrustumTest(dest) | VertexCache.vSize[VertexCache.vType].Format); + dest[0].flag = (u32)(clipToFrustumTest(dest) | VertexCache.vSize[VertexCache.vType].Format); dest[1].flag = dest[0].flag; // to DC Space, project homogenous vertex - if ( (dest[0].flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) + if ((dest[0].flag & VERTEX4D_CLIPMASK) == VERTEX4D_INSIDE) { - ndc_2_dc_and_project ( dest+1, dest, s4DVertex_ofs(1)); + ndc_2_dc_and_project(dest + s4DVertex_proj(0), dest + s4DVertex_ofs(0), s4DVertex_ofs(1)); } } //todo: this should return only index -s4DVertexPair* CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceIndex ) const +s4DVertexPair* CBurningVideoDriver::VertexCache_getVertex(const u32 sourceIndex) const { - for ( size_t i = 0; i < VERTEXCACHE_ELEMENT; ++i ) + for (size_t i = 0; i < VERTEXCACHE_ELEMENT; ++i) { - if ( VertexCache.info[ i ].index == sourceIndex ) + if (VertexCache.info[i].index == sourceIndex) { return VertexCache.mem.data + s4DVertex_ofs(i); } @@ -1927,8 +1847,8 @@ s4DVertexPair* CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceInde void CBurningVideoDriver::VertexCache_get(s4DVertexPair* face[4]) { // next primitive must be complete in cache - if ( VertexCache.indicesIndex - VertexCache.indicesRun < VertexCache.primitiveHasVertex && - VertexCache.indicesIndex < VertexCache.indexCount + if (VertexCache.indicesIndex - VertexCache.indicesRun < VertexCache.primitiveHasVertex && + VertexCache.indicesIndex < VertexCache.indexCount ) { @@ -1949,74 +1869,74 @@ void CBurningVideoDriver::VertexCache_get(s4DVertexPair* face[4]) u32 dIndex = 0; u32 sourceIndex = 0; - while ( VertexCache.indicesIndex < VertexCache.indexCount && - fillIndex < VERTEXCACHE_ELEMENT - ) + while (VertexCache.indicesIndex < VertexCache.indexCount && + fillIndex < VERTEXCACHE_ELEMENT + ) { - switch ( VertexCache.iType ) + switch (VertexCache.iType) { - case E4IT_16BIT: - sourceIndex = ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ]; - break; - case E4IT_32BIT: - sourceIndex = ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ]; - break; - default: - case E4IT_NONE: - sourceIndex = VertexCache.indicesIndex; - break; + case E4IT_16BIT: + sourceIndex = ((u16*)VertexCache.indices)[VertexCache.indicesIndex]; + break; + case E4IT_32BIT: + sourceIndex = ((u32*)VertexCache.indices)[VertexCache.indicesIndex]; + break; + default: + case E4IT_NONE: + sourceIndex = VertexCache.indicesIndex; + break; } VertexCache.indicesIndex += 1; // if not exist, push back s32 exist = 0; - for ( dIndex = 0; dIndex < fillIndex; ++dIndex ) + for (dIndex = 0; dIndex < fillIndex; ++dIndex) { - if (VertexCache.info_temp[ dIndex ].index == sourceIndex ) + if (VertexCache.info_temp[dIndex].index == sourceIndex) { exist = 1; break; } } - if ( 0 == exist ) + if (0 == exist) { VertexCache.info_temp[fillIndex++].index = sourceIndex; } } // clear marks - for ( i = 0; i!= VERTEXCACHE_ELEMENT; ++i ) + for (i = 0; i != VERTEXCACHE_ELEMENT; ++i) { VertexCache.info[i].hit = 0; } // mark all existing - for ( i = 0; i!= fillIndex; ++i ) + for (i = 0; i != fillIndex; ++i) { - for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) + for (dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex) { - if ( VertexCache.info[ dIndex ].index == VertexCache.info_temp[i].index ) + if (VertexCache.info[dIndex].index == VertexCache.info_temp[i].index) { VertexCache.info_temp[i].hit = dIndex; - VertexCache.info[ dIndex ].hit = 1; + VertexCache.info[dIndex].hit = 1; break; } } } // fill new - for ( i = 0; i!= fillIndex; ++i ) + for (i = 0; i != fillIndex; ++i) { - if (VertexCache.info_temp[i].hit != VERTEXCACHE_MISS ) + if (VertexCache.info_temp[i].hit != VERTEXCACHE_MISS) continue; - for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) + for (dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex) { - if ( 0 == VertexCache.info[dIndex].hit ) + if (0 == VertexCache.info[dIndex].hit) { - VertexCache_fill (VertexCache.info_temp[i].index, dIndex ); + VertexCache_fill(VertexCache.info_temp[i].index, dIndex); VertexCache.info[dIndex].hit += 1; VertexCache.info_temp[i].hit = dIndex; break; @@ -2028,33 +1948,33 @@ void CBurningVideoDriver::VertexCache_get(s4DVertexPair* face[4]) //const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); const u32 i0 = VertexCache.pType != scene::EPT_TRIANGLE_FAN ? VertexCache.indicesRun : 0; - switch ( VertexCache.iType ) + switch (VertexCache.iType) { - case E4IT_16BIT: - { - const u16* p = (const u16*) VertexCache.indices; - face[0] = VertexCache_getVertex ( p[ i0 ] ); - face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); - face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); - } - break; + case E4IT_16BIT: + { + const u16* p = (const u16*)VertexCache.indices; + face[0] = VertexCache_getVertex(p[i0]); + face[1] = VertexCache_getVertex(p[VertexCache.indicesRun + 1]); + face[2] = VertexCache_getVertex(p[VertexCache.indicesRun + 2]); + } + break; - case E4IT_32BIT: - { - const u32* p = (const u32*) VertexCache.indices; - face[0] = VertexCache_getVertex ( p[ i0 ] ); - face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); - face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); - } - break; + case E4IT_32BIT: + { + const u32* p = (const u32*)VertexCache.indices; + face[0] = VertexCache_getVertex(p[i0]); + face[1] = VertexCache_getVertex(p[VertexCache.indicesRun + 1]); + face[2] = VertexCache_getVertex(p[VertexCache.indicesRun + 2]); + } + break; - case E4IT_NONE: - face[0] = VertexCache_getVertex ( VertexCache.indicesRun + 0 ); - face[1] = VertexCache_getVertex ( VertexCache.indicesRun + 1 ); - face[2] = VertexCache_getVertex ( VertexCache.indicesRun + 2 ); + case E4IT_NONE: + face[0] = VertexCache_getVertex(VertexCache.indicesRun + 0); + face[1] = VertexCache_getVertex(VertexCache.indicesRun + 1); + face[2] = VertexCache_getVertex(VertexCache.indicesRun + 2); break; - default: - face[0] = face[1] = face[2] = VertexCache_getVertex(VertexCache.indicesRun + 0); + default: + face[0] = face[1] = face[2] = VertexCache_getVertex(VertexCache.indicesRun + 0); break; } face[3] = face[0]; // quad unsupported @@ -2064,11 +1984,11 @@ void CBurningVideoDriver::VertexCache_get(s4DVertexPair* face[4]) /*! */ -int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, - const void* indices, u32 primitiveCount, - E_VERTEX_TYPE vType, - scene::E_PRIMITIVE_TYPE pType, - E_INDEX_TYPE iType) +int CBurningVideoDriver::VertexCache_reset(const void* vertices, u32 vertexCount, + const void* indices, u32 primitiveCount, + E_VERTEX_TYPE vType, + scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) { // These calls would lead to crashes due to wrong index usage. @@ -2087,18 +2007,18 @@ int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCou switch (Material.org.MaterialType) // (Material.Fallback_MaterialType) { - case EMT_REFLECTION_2_LAYER: - case EMT_TRANSPARENT_REFLECTION_2_LAYER: - VertexCache.vType = E4VT_REFLECTION_MAP; - break; - default: - VertexCache.vType = (e4DVertexType)vType; - break; + case EMT_REFLECTION_2_LAYER: + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + VertexCache.vType = E4VT_REFLECTION_MAP; + break; + default: + VertexCache.vType = (e4DVertexType)vType; + break; } //check material SVSize* vSize = VertexCache.vSize; - for (int m = (int)vSize[VertexCache.vType].TexSize-1; m >= 0 ; --m) + for (int m = (int)vSize[VertexCache.vType].TexSize - 1; m >= 0; --m) { ITexture* tex = MAT_TEXTURE(m); if (!tex) @@ -2115,12 +2035,12 @@ int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCou VertexCache.indicesIndex = 0; VertexCache.indicesRun = 0; - switch ( iType ) + switch (iType) { - case EIT_16BIT: VertexCache.iType = E4IT_16BIT; break; - case EIT_32BIT: VertexCache.iType = E4IT_32BIT; break; - default: - VertexCache.iType = (e4DIndexType)iType; break; + case EIT_16BIT: VertexCache.iType = E4IT_16BIT; break; + case EIT_32BIT: VertexCache.iType = E4IT_32BIT; break; + default: + VertexCache.iType = (e4DIndexType)iType; break; } if (!VertexCache.indices) VertexCache.iType = E4IT_NONE; @@ -2128,65 +2048,65 @@ int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCou VertexCache.pType = pType; VertexCache.primitiveHasVertex = 3; VertexCache.indicesPitch = 1; - switch ( VertexCache.pType ) + switch (VertexCache.pType) { // most types here will not work as expected, only triangles/triangle_fan // is known to work. - case scene::EPT_POINTS: - VertexCache.indexCount = primitiveCount; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 1; - break; - case scene::EPT_LINE_STRIP: - VertexCache.indexCount = primitiveCount+1; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 2; - break; - case scene::EPT_LINE_LOOP: - VertexCache.indexCount = primitiveCount+1; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 2; - break; - case scene::EPT_LINES: - VertexCache.indexCount = 2*primitiveCount; - VertexCache.indicesPitch = 2; - VertexCache.primitiveHasVertex = 2; - break; - case scene::EPT_TRIANGLE_STRIP: - VertexCache.indexCount = primitiveCount+2; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 3; - break; - case scene::EPT_TRIANGLES: - VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount; - VertexCache.indicesPitch = 3; - VertexCache.primitiveHasVertex = 3; - break; - case scene::EPT_TRIANGLE_FAN: - VertexCache.indexCount = primitiveCount + 2; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 3; - break; - case scene::EPT_QUAD_STRIP: - VertexCache.indexCount = 2*primitiveCount + 2; - VertexCache.indicesPitch = 2; - VertexCache.primitiveHasVertex = 4; - break; - case scene::EPT_QUADS: - VertexCache.indexCount = 4*primitiveCount; - VertexCache.indicesPitch = 4; - VertexCache.primitiveHasVertex = 4; - break; - case scene::EPT_POLYGON: - VertexCache.indexCount = primitiveCount+1; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = primitiveCount; - break; - case scene::EPT_POINT_SPRITES: - VertexCache.indexCount = primitiveCount; - VertexCache.indicesPitch = 1; - VertexCache.primitiveHasVertex = 1; - break; + case scene::EPT_POINTS: + VertexCache.indexCount = primitiveCount; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 1; + break; + case scene::EPT_LINE_STRIP: + VertexCache.indexCount = primitiveCount + 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 2; + break; + case scene::EPT_LINE_LOOP: + VertexCache.indexCount = primitiveCount + 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 2; + break; + case scene::EPT_LINES: + VertexCache.indexCount = 2 * primitiveCount; + VertexCache.indicesPitch = 2; + VertexCache.primitiveHasVertex = 2; + break; + case scene::EPT_TRIANGLE_STRIP: + VertexCache.indexCount = primitiveCount + 2; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 3; + break; + case scene::EPT_TRIANGLES: + VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount; + VertexCache.indicesPitch = 3; + VertexCache.primitiveHasVertex = 3; + break; + case scene::EPT_TRIANGLE_FAN: + VertexCache.indexCount = primitiveCount + 2; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 3; + break; + case scene::EPT_QUAD_STRIP: + VertexCache.indexCount = 2 * primitiveCount + 2; + VertexCache.indicesPitch = 2; + VertexCache.primitiveHasVertex = 4; + break; + case scene::EPT_QUADS: + VertexCache.indexCount = 4 * primitiveCount; + VertexCache.indicesPitch = 4; + VertexCache.primitiveHasVertex = 4; + break; + case scene::EPT_POLYGON: + VertexCache.indexCount = primitiveCount + 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = primitiveCount; + break; + case scene::EPT_POINT_SPRITES: + VertexCache.indexCount = primitiveCount; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 1; + break; } //memset( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) ); @@ -2201,8 +2121,8 @@ int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCou //! draws a vertex primitive list void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, - const void* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) @@ -2220,7 +2140,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert //Matrices needed for this primitive transform_calc(ETS_PROJ_MODEL_VIEW); - if ( Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM | TL_FOG)) ) + if (Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM | TL_FOG))) { transform_calc(ETS_MODEL_VIEW); transform_calc(ETS_NORMAL); @@ -2233,7 +2153,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert size_t vertex_from_clipper; // from VertexCache or CurrentOut size_t has_vertex_run; - for ( size_t primitive_run = 0; primitive_run < primitiveCount; ++primitive_run) + for (size_t primitive_run = 0; primitive_run < primitiveCount; ++primitive_run) { //collect pointer to face vertices VertexCache_get(face); @@ -2253,14 +2173,14 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert clipMask_i &= VERTEX4D_CLIPMASK; clipMask_o &= VERTEX4D_CLIPMASK; - if (clipMask_i != VERTEX4D_INSIDE ) + if (clipMask_i != VERTEX4D_INSIDE) { // if primitive fully outside or outside on same side continue; vOut = 0; vertex_from_clipper = 0; } - else if (clipMask_o == VERTEX4D_INSIDE ) + else if (clipMask_o == VERTEX4D_INSIDE) { // if primitive fully inside vOut = VertexCache.primitiveHasVertex; @@ -2280,7 +2200,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert vertex_from_clipper = 1; // to DC Space, project homogenous vertex - ndc_2_dc_and_project(Clipper.data + s4DVertex_proj(0), Clipper.data, s4DVertex_ofs(vOut)); + ndc_2_dc_and_project(Clipper.data + s4DVertex_proj(0), Clipper.data + s4DVertex_ofs(0), s4DVertex_ofs(vOut)); } #else { @@ -2301,7 +2221,19 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert } //area of primitive in device space - f32 dc_area = screenarea_inside(face); + // projected triangle screen area is used for culling ( sign of normal ) and mipmap selection + //f32 dc_area = screenarea_inside(face); + + // crossproduct (area of parallelogram * 0.5 = triangle screen size) + f32 dc_area; + { + const sVec4& v0 = (face[0] + s4DVertex_proj(0))->Pos; + const sVec4& v1 = (face[1] + s4DVertex_proj(0))->Pos; + const sVec4& v2 = (face[2] + s4DVertex_proj(0))->Pos; + + //dc_area = a.x * b.y - b.x * a.y; + dc_area = ((v1.x - v0.x) * (v2.y - v0.y) - (v2.x - v0.x) * (v1.y - v0.y)) * 0.5f; + } //geometric clipping has problem with invisible or very small Triangles //size_t sign = dc_area < 0.001f ? CULL_BACK : dc_area > 0.001f ? CULL_FRONT : CULL_INVISIBLE; @@ -2312,7 +2244,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert if (Material.CullFlag & sign) break; //continue; - //select mipmap ratio between drawing space and texture space + //select mipmap ratio between drawing space and texture space (for multiply divide here) dc_area = reciprocal_zero(dc_area); // select mipmap @@ -2321,17 +2253,29 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert video::CSoftwareTexture2* tex = MAT_TEXTURE(m); //only guessing: take more detail (lower mipmap) in light+bump textures + f32 lod_bias = 0.100f;// core::clamp(map_value((f32)ScreenSize.Width * ScreenSize.Height, 160 * 120, 640 * 480, 1.f / 8.f, 1.f / 8.f), 0.01f, 1.f); + //assume transparent add is ~50% transparent -> more detail - f32 lod_bias = Material.org.MaterialType == EMT_TRANSPARENT_ADD_COLOR ? 0.1f : 0.33f; + switch (Material.org.MaterialType) + { + case EMT_TRANSPARENT_ADD_COLOR: + case EMT_TRANSPARENT_ALPHA_CHANNEL: + lod_bias *= 0.5f; + break; + default: + break; + } lod_bias *= tex->get_lod_bias(); + //lod_bias += Material.org.TextureLayer[m].LODBias * 0.125f; + s32 lodFactor = lodFactor_inside(face, m, dc_area, lod_bias); CurrentShader->setTextureParam(m, tex, lodFactor); //currently shader receives texture coordinate as Pixelcoo of 1 Texture select_polygon_mipmap_inside(face, m, tex->getTexBound()); } - - CurrentShader->drawWireFrameTriangle(face[0] + 1, face[1] + 1, face[2] + 1); + + CurrentShader->drawWireFrameTriangle(face[0] + s4DVertex_proj(0), face[1] + s4DVertex_proj(0), face[2] + s4DVertex_proj(0)); vertex_from_clipper = 1; } @@ -2351,23 +2295,23 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert //! \param color: New color of the ambient light. void CBurningVideoDriver::setAmbientLight(const SColorf& color) { - EyeSpace.Global_AmbientLight.setColorf ( color ); + EyeSpace.Global_AmbientLight.setColorf(color); } //! adds a dynamic light s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) { - (void) CNullDriver::addDynamicLight( dl ); + (void)CNullDriver::addDynamicLight(dl); SBurningShaderLight l; -// l.org = dl; + // l.org = dl; l.Type = dl.Type; l.LightIsOn = true; - l.AmbientColor.setColorf ( dl.AmbientColor ); - l.DiffuseColor.setColorf ( dl.DiffuseColor ); - l.SpecularColor.setColorf ( dl.SpecularColor ); + l.AmbientColor.setColorf(dl.AmbientColor); + l.DiffuseColor.setColorf(dl.DiffuseColor); + l.SpecularColor.setColorf(dl.SpecularColor); //should always be valid? sVec4 nDirection; @@ -2377,77 +2321,77 @@ s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) nDirection.normalize_dir_xyz(); - switch ( dl.Type ) + switch (dl.Type) { - case ELT_DIRECTIONAL: - l.pos.x = dl.Position.X; - l.pos.y = dl.Position.Y; - l.pos.z = dl.Position.Z; - l.pos.w = 0.f; + case ELT_DIRECTIONAL: + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 0.f; - l.constantAttenuation = 1.f; - l.linearAttenuation = 0.f; - l.quadraticAttenuation = 0.f; + l.constantAttenuation = 1.f; + l.linearAttenuation = 0.f; + l.quadraticAttenuation = 0.f; - l.spotDirection.x = -nDirection.x; - l.spotDirection.y = -nDirection.y; - l.spotDirection.z = -nDirection.z; - l.spotDirection.w = 0.f; - l.spotCosCutoff = -1.f; - l.spotCosInnerCutoff = 1.f; - l.spotExponent = 0.f; - break; + l.spotDirection.x = -nDirection.x; + l.spotDirection.y = -nDirection.y; + l.spotDirection.z = -nDirection.z; + l.spotDirection.w = 0.f; + l.spotCosCutoff = -1.f; + l.spotCosInnerCutoff = 1.f; + l.spotExponent = 0.f; + break; - case ELT_POINT: - l.pos.x = dl.Position.X; - l.pos.y = dl.Position.Y; - l.pos.z = dl.Position.Z; - l.pos.w = 1.f; + case ELT_POINT: + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 1.f; - l.constantAttenuation = dl.Attenuation.X; - l.linearAttenuation = dl.Attenuation.Y; - l.quadraticAttenuation = dl.Attenuation.Z; + l.constantAttenuation = dl.Attenuation.X; + l.linearAttenuation = dl.Attenuation.Y; + l.quadraticAttenuation = dl.Attenuation.Z; - l.spotDirection.x = -nDirection.x; - l.spotDirection.y = -nDirection.y; - l.spotDirection.z = -nDirection.z; - l.spotDirection.w = 0.f; - l.spotCosCutoff = -1.f; - l.spotCosInnerCutoff = 1.f; - l.spotExponent = 0.f; - break; + l.spotDirection.x = -nDirection.x; + l.spotDirection.y = -nDirection.y; + l.spotDirection.z = -nDirection.z; + l.spotDirection.w = 0.f; + l.spotCosCutoff = -1.f; + l.spotCosInnerCutoff = 1.f; + l.spotExponent = 0.f; + break; - case ELT_SPOT: - l.pos.x = dl.Position.X; - l.pos.y = dl.Position.Y; - l.pos.z = dl.Position.Z; - l.pos.w = 1.f; + case ELT_SPOT: + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 1.f; - l.constantAttenuation = dl.Attenuation.X; - l.linearAttenuation = dl.Attenuation.Y; - l.quadraticAttenuation = dl.Attenuation.Z; + l.constantAttenuation = dl.Attenuation.X; + l.linearAttenuation = dl.Attenuation.Y; + l.quadraticAttenuation = dl.Attenuation.Z; - l.spotDirection.x = nDirection.x; - l.spotDirection.y = nDirection.y; - l.spotDirection.z = nDirection.z; - l.spotDirection.w = 0.0f; - l.spotCosCutoff = cosf(dl.OuterCone * 2.0f * core::DEGTORAD * 0.5f); - l.spotCosInnerCutoff = cosf(dl.InnerCone * 2.0f * core::DEGTORAD * 0.5f); - l.spotExponent = dl.Falloff; - break; - default: - break; + l.spotDirection.x = nDirection.x; + l.spotDirection.y = nDirection.y; + l.spotDirection.z = nDirection.z; + l.spotDirection.w = 0.0f; + l.spotCosCutoff = cosf(dl.OuterCone * 2.0f * core::DEGTORAD * 0.5f); + l.spotCosInnerCutoff = cosf(dl.InnerCone * 2.0f * core::DEGTORAD * 0.5f); + l.spotExponent = dl.Falloff; + break; + default: + break; } //which means ETS_VIEW - setTransform(ETS_WORLD,irr::core::IdentityMatrix); + setTransform(ETS_WORLD, irr::core::IdentityMatrix); transform_calc(ETS_MODEL_VIEW); const core::matrix4* matrix = Transformation[TransformationStack]; - transformVec4Vec4(matrix[ETS_MODEL_VIEW], &l.pos4.x, &l.pos.x ); - rotateVec3Vec4(matrix[ETS_MODEL_VIEW], &l.spotDirection4.x, &l.spotDirection.x ); + transformVec4Vec4(matrix[ETS_MODEL_VIEW], &l.pos4.x, &l.pos.x); + rotateVec3Vec4(matrix[ETS_MODEL_VIEW], &l.spotDirection4.x, &l.spotDirection.x); - EyeSpace.Light.push_back ( l ); + EyeSpace.Light.push_back(l); return EyeSpace.Light.size() - 1; } @@ -2455,7 +2399,7 @@ s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) //! Turns a dynamic light on or off void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) { - if((u32)lightIndex < EyeSpace.Light.size()) + if ((u32)lightIndex < EyeSpace.Light.size()) { EyeSpace.Light[lightIndex].LightIsOn = turnOn; } @@ -2464,7 +2408,7 @@ void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) //! deletes all dynamic lights there are void CBurningVideoDriver::deleteAllDynamicLights() { - EyeSpace.reset (); + EyeSpace.reset(); CNullDriver::deleteAllDynamicLights(); } @@ -2479,14 +2423,14 @@ u32 CBurningVideoDriver::getMaximalDynamicLightAmount() const //! sets a material void CBurningVideoDriver::setMaterial(const SMaterial& material) { -// ---------- Override + // ---------- Override Material.org = material; OverrideMaterial.apply(Material.org); const SMaterial& in = Material.org; -// ---------- Notify Shader - // unset old material + // ---------- Notify Shader + // unset old material u32 mi; mi = (u32)Material.lastMaterial.MaterialType; if (mi != material.MaterialType && mi < MaterialRenderers.size()) @@ -2515,27 +2459,27 @@ void CBurningVideoDriver::setMaterial(const SMaterial& material) #ifdef SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM for (u32 m = 0; m < BURNING_MATERIAL_MAX_TEXTURES /*&& m < vSize[VertexCache.vType].TexSize*/; ++m) { - setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + m),in.getTextureMatrix(m)); - flag[ETS_TEXTURE_0+m] &= ~ETF_TEXGEN_MASK; + setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + m), in.getTextureMatrix(m)); + flag[ETS_TEXTURE_0 + m] &= ~ETF_TEXGEN_MASK; } #endif #ifdef SOFTWARE_DRIVER_2_LIGHTING - Material.AmbientColor.setA8R8G8B8( in.AmbientColor.color ); - Material.DiffuseColor.setA8R8G8B8( in.ColorMaterial ? 0xFFFFFFFF : in.DiffuseColor.color ); - Material.EmissiveColor.setA8R8G8B8(in.EmissiveColor.color ); - Material.SpecularColor.setA8R8G8B8( in.SpecularColor.color ); + Material.AmbientColor.setA8R8G8B8(in.AmbientColor.color); + Material.DiffuseColor.setA8R8G8B8(in.ColorMaterial ? 0xFFFFFFFF : in.DiffuseColor.color); + Material.EmissiveColor.setA8R8G8B8(in.EmissiveColor.color); + Material.SpecularColor.setA8R8G8B8(in.SpecularColor.color); burning_setbit(EyeSpace.TL_Flag, in.Lighting, TL_LIGHT); - burning_setbit( EyeSpace.TL_Flag, (in.Shininess != 0.f) & (in.SpecularColor.color & 0x00ffffff), TL_SPECULAR ); - burning_setbit( EyeSpace.TL_Flag, in.FogEnable, TL_FOG ); - burning_setbit( EyeSpace.TL_Flag, in.NormalizeNormals, TL_NORMALIZE_NORMALS ); + burning_setbit(EyeSpace.TL_Flag, (in.Shininess != 0.f) && (in.SpecularColor.color & 0x00ffffff), TL_SPECULAR); + burning_setbit(EyeSpace.TL_Flag, in.FogEnable, TL_FOG); + burning_setbit(EyeSpace.TL_Flag, in.NormalizeNormals, TL_NORMALIZE_NORMALS); //if (EyeSpace.Flags & SPECULAR ) EyeSpace.Flags |= NORMALIZE_NORMALS; #endif - //--------------- setCurrentShader +//--------------- setCurrentShader ITexture* texture0 = in.getTexture(0); ITexture* texture1 = in.getTexture(1); @@ -2660,7 +2604,7 @@ void CBurningVideoDriver::setMaterial(const SMaterial& material) { shader = Material.depth_test ? ETR_GOURAUD : shader == ETR_TEXTURE_GOURAUD_VERTEX_ALPHA ? - ETR_GOURAUD_ALPHA_NOZ: // 2D Gradient + ETR_GOURAUD_ALPHA_NOZ : // 2D Gradient ETR_GOURAUD_NOZ; shader = ETR_COLOR; @@ -2693,17 +2637,17 @@ void CBurningVideoDriver::setMaterial(const SMaterial& material) CurrentShader->setTLFlag(EyeSpace.TL_Flag); if (EyeSpace.TL_Flag & TL_FOG) CurrentShader->setFog(FogColor); if (EyeSpace.TL_Flag & TL_SCISSOR) CurrentShader->setScissor(Scissor); - CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort, Interlaced); CurrentShader->OnSetMaterial(Material); CurrentShader->pushEdgeTest(in.Wireframe, in.PointCloud, 0); } -/* - mi = (u32)Material.org.MaterialType; - if (mi < MaterialRenderers.size()) - MaterialRenderers[mi].Renderer->OnRender(this, (video::E_VERTEX_TYPE)VertexCache.vType); -*/ + /* + mi = (u32)Material.org.MaterialType; + if (mi < MaterialRenderers.size()) + MaterialRenderers[mi].Renderer->OnRender(this, (video::E_VERTEX_TYPE)VertexCache.vType); + */ } @@ -2713,7 +2657,7 @@ void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, { CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); - EyeSpace.fog_scale = reciprocal_zero2(FogEnd - FogStart); + EyeSpace.fog_scale = reciprocal_zero(FogEnd - FogStart); } @@ -2724,7 +2668,7 @@ void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, /*! applies lighting model */ -void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) +void CBurningVideoDriver::lightVertex_eye(s4DVertex* dest, u32 vertexargb) { //gl_FrontLightModelProduct.sceneColor = gl_FrontMaterial.emission + gl_FrontMaterial.ambient * gl_LightModel.ambient @@ -2807,7 +2751,7 @@ void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) //specular += light.SpecularColor * pow(max(dot(Eyespace.normal,lighthalf),0,Material.org.Shininess)*attenuation specular.mad_rgb(light.SpecularColor, - powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess)*attenuation + powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess) * attenuation ); break; @@ -2855,7 +2799,7 @@ void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) //specular += light.SpecularColor * pow(max(dot(Eyespace.normal,lighthalf),0,Material.org.Shininess)*attenuation specular.mad_rgb(light.SpecularColor, - powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess)*attenuation + powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess) * attenuation ); break; @@ -2886,17 +2830,17 @@ void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) specular.sat_xyz(dest->Color[1], Material.SpecularColor); } else - if ( !(EyeSpace.TL_Flag & TL_LIGHT0_IS_NORMAL_MAP) && - (VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_MASK_LIGHT) - ) - { - specular.sat_xyz(dest->LightTangent[0], Material.SpecularColor); - } - else + if (!(EyeSpace.TL_Flag & TL_LIGHT0_IS_NORMAL_MAP) && + (VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_MASK_LIGHT) + ) + { + specular.sat_xyz(dest->LightTangent[0], Material.SpecularColor); + } + else #endif - { - dColor.mad_rgbv(specular, Material.SpecularColor); - } + { + dColor.mad_rgbv(specular, Material.SpecularColor); + } dColor.mad_rgbv(ambient, Material.AmbientColor); @@ -2908,7 +2852,7 @@ void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) } #endif - +/* CImage* getImage(const video::ITexture* texture) { if (!texture) return 0; @@ -2928,7 +2872,7 @@ CImage* getImage(const video::ITexture* texture) } return img; } - +*/ /* draw2DImage with single color scales into destination quad & cliprect(more like viewport) draw2DImage with 4 color scales on destination and cliprect is scissor @@ -3008,84 +2952,6 @@ void CBurningVideoDriver::draw2DRectangle(const core::rect& position, - - -#if 0 -void transform_for_BlitJob2D( SBlitJob& out, - const S3DVertex quad2DVertices[4], const core::dimension2d& renderTargetSize, - CBurningVideoDriver* driver -) -{ - //assume. z = 0.f, w = 1.f - //MVP 2D - core::matrix4 m; - m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); - m.setTranslation(core::vector3df(-1.f, 1.f, 0)); - - //setTransform(ETS_WORLD, m); - //m.setTranslation(core::vector3df(0.375f, 0.375f, 0.0f)); - //setTransform(ETS_VIEW, m); - - s4DVertexPair v[4*sizeof_s4DVertexPairRel]; - for (int i = 0; i < 4; ++i) - { - m.transformVect(&v[s4DVertex_ofs(i)].Pos.x, quad2DVertices[i].Pos); - v[s4DVertex_ofs(i)].Tex[0].x = quad2DVertices[i].TCoords.X; - v[s4DVertex_ofs(i)].Tex[0].y = quad2DVertices[i].TCoords.Y; - v[s4DVertex_ofs(i)].Color[0].setA8R8G8B8(quad2DVertices[i].Color.color); - v[s4DVertex_ofs(i)].flag = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1; - v[s4DVertex_ofs(i)].flag |= clipToFrustumTest(v + i); - } - - size_t vOut = driver->clipToFrustum(4); - - struct s2DVertex - { - union - { - struct { - f32 x, y; - f32 u, v; - f32 a, r, g, b; - }; - f32 attr[8]; - }; - - // f = a * t + b * ( 1 - t ) - void interpolate(const s2DVertex& b, const s2DVertex& a, const f32 t) - { - for (int i = 0; i < 8; ++i) - { - attr[i] = b.attr[i] + ((a.attr[i] - b.attr[i]) * t); - } - } - - }; - - // 0 5 - f32 m2[2]; - m2[0] = renderTargetSize.Width ? 2.f / renderTargetSize.Width : 0.f; - m2[1] = renderTargetSize.Height ? -2.f / renderTargetSize.Height : 0.f; - - s2DVertex p[4]; - for (int i = 0; i < 4; ++i) - { - p[i].x = quad2DVertices[i].Pos.X*m2[0] - 1.f; - p[i].y = quad2DVertices[i].Pos.Y*m2[1] + 1.f; - p[i].u = quad2DVertices[i].TCoords.X; - p[i].v = quad2DVertices[i].TCoords.Y; - - p[i].a = quad2DVertices[i].Color.getAlpha() * (1.f / 255.f); - p[i].r = quad2DVertices[i].Color.getRed() * (1.f / 255.f); - p[i].g = quad2DVertices[i].Color.getBlue() * (1.f / 255.f); - p[i].b = quad2DVertices[i].Color.getGreen() * (1.f / 255.f); - - } - -} -#endif - - //! Enable the 2d override material void CBurningVideoDriver::enableMaterial2D(bool enable) { @@ -3109,7 +2975,7 @@ size_t compare_2d_material(const SMaterial& a, const SMaterial& b) return flag; } -void CBurningVideoDriver::setRenderStates2DMode(const video::SColor& color, video::ITexture* texture, bool useAlphaChannelOfTexture) +void CBurningVideoDriver::setRenderStates2DMode(const video::SColor& color, const video::ITexture* texture, bool useAlphaChannelOfTexture) { //save current 3D Material //Material.save3D = Material.org; @@ -3142,7 +3008,7 @@ void CBurningVideoDriver::setRenderStates2DMode(const video::SColor& color, vide bool mip = false; const SMaterial& currentMaterial = (!OverrideMaterial2DEnabled) ? InitMaterial2D : OverrideMaterial2D; - mip = currentMaterial.TextureLayer[0].BilinearFilter; + mip = currentMaterial.TextureLayer[0].Texture && currentMaterial.TextureLayer[0].BilinearFilter; Material.mat2D.setFlag(video::EMF_BILINEAR_FILTER, mip); @@ -3162,22 +3028,25 @@ void CBurningVideoDriver::setRenderStates2DMode(const video::SColor& color, vide m.makeIdentity(); setTransform(ETS_WORLD, m); - if ( mip ) m.setTranslation(core::vector3df(0.375f, 0.375f, 0.0f)); + if (mip) + m.setTranslation(core::vector3df(IRRLICHT_2D_TEXEL_OFFSET, IRRLICHT_2D_TEXEL_OFFSET, 0.0f)); setTransform(ETS_VIEW, m); - buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[TransformationStack], ViewPort, mip ? -0.187f : 0.f); - + //Tweak 2D Pixel Center for openGL compatibility (guessing) + //buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[TransformationStack], ViewPort, mip ? (IRRLICHT_2D_TEXEL_OFFSET) * 0.5f : 0.f); } //compare - if (compare_2d_material(Material.org,Material.mat2D)) + if (compare_2d_material(Material.org, Material.mat2D)) { setMaterial(Material.mat2D); } if (CurrentShader) { CurrentShader->setPrimitiveColor(color.color); + CurrentShader->setTLFlag(EyeSpace.TL_Flag); + if (EyeSpace.TL_Flag & TL_SCISSOR) CurrentShader->setScissor(Scissor); } } @@ -3283,10 +3152,7 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); - //SBlitJob job; - //transform_for_BlitJob2D(job, Quad2DVertices, renderTargetSize,this); - - setRenderStates2DMode(color, (video::ITexture*) texture, useAlphaChannelOfTexture); + setRenderStates2DMode(color, texture, useAlphaChannelOfTexture); drawVertexPrimitiveList(Quad2DVertices, 4, quad_triangle_indexList, 2, @@ -3309,7 +3175,7 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core sourceRect.UpperLeftCorner.X * invW, sourceRect.UpperLeftCorner.Y * invH, sourceRect.LowerRightCorner.X * invW, - sourceRect.LowerRightCorner.Y *invH); + sourceRect.LowerRightCorner.Y * invH); const video::SColor temp[4] = { @@ -3338,8 +3204,6 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - if (clipRect) { if (!clipRect->isValid()) @@ -3347,29 +3211,25 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core //glEnable(GL_SCISSOR_TEST); EyeSpace.TL_Flag |= TL_SCISSOR; - setScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y, + setScissor(clipRect->UpperLeftCorner.X, clipRect->UpperLeftCorner.Y,//renderTargetSize.Height - clipRect->LowerRightCorner.Y clipRect->getWidth(), clipRect->getHeight()); } video::SColor alphaTest; alphaTest.color = useColor[0].color & useColor[0].color & useColor[0].color & useColor[0].color; - //SBlitJob job; - //transform_for_BlitJob2D(job, Quad2DVertices, renderTargetSize, this); - setRenderStates2DMode(alphaTest, (video::ITexture*) texture, useAlphaChannelOfTexture); + setRenderStates2DMode(alphaTest,texture, useAlphaChannelOfTexture); drawVertexPrimitiveList(Quad2DVertices, 4, quad_triangle_indexList, 2, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); - if (clipRect) EyeSpace.TL_Flag &= ~TL_SCISSOR; setRenderStates3DMode(); - } @@ -3427,15 +3287,15 @@ void CBurningVideoDriver::draw2DRectangle(const core::rect& position, //! Draws a 2d line. void CBurningVideoDriver::draw2DLine(const core::position2d& start, - const core::position2d& end, - SColor color) + const core::position2d& end, + SColor color) { - drawLine(RenderTargetSurface, start, end, color ); + drawLine(RenderTargetSurface, start, end, color); } //! Draws a pixel -void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color) +void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor& color) { RenderTargetSurface->setPixel(x, y, color, true); } @@ -3447,13 +3307,13 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 core::dimension2d realSize(size); -/* - if (realSize.Width % 2) - realSize.Width += 1; + /* + if (realSize.Width % 2) + realSize.Width += 1; - if (realSize.Height % 2) - realSize.Height += 1; -*/ + if (realSize.Height % 2) + realSize.Height += 1; + */ if (ScreenSize != realSize) { if (ViewPort.getWidth() == (s32)ScreenSize.Width && @@ -3471,10 +3331,10 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) if (BackBuffer) BackBuffer->drop(); - BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, realSize); + BackBuffer = new CImage(SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT, realSize); if (resetRT) - setRenderTargetImage(BackBuffer); + setRenderTargetImage2(BackBuffer); } } @@ -3482,10 +3342,11 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) //! returns the current render target size const core::dimension2d& CBurningVideoDriver::getCurrentRenderTargetSize() const { - return RenderTargetSize; + return (RenderTargetSurface == BackBuffer) ? ScreenSize : RenderTargetSize; } + //! Draws a 3d line. void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color_start) @@ -3499,56 +3360,53 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start, transform_calc(ETS_PROJ_MODEL_VIEW); const core::matrix4* matrix = Transformation[TransformationStack]; - matrix[ETS_PROJ_MODEL_VIEW].transformVect ( &v[0].Pos.x, start ); - matrix[ETS_PROJ_MODEL_VIEW].transformVect ( &v[2].Pos.x, end ); + matrix[ETS_PROJ_MODEL_VIEW].transformVect(&v[s4DVertex_ofs(0)].Pos.x, start); + matrix[ETS_PROJ_MODEL_VIEW].transformVect(&v[s4DVertex_ofs(1)].Pos.x, end); #if BURNING_MATERIAL_MAX_COLORS > 0 - v[0].Color[0].setA8R8G8B8 ( color_start.color ); - v[2].Color[0].setA8R8G8B8 ( color_end.color ); + v[s4DVertex_ofs(0)].Color[0].setA8R8G8B8(color_start.color); + v[s4DVertex_ofs(1)].Color[0].setA8R8G8B8(color_end.color); #endif - u32 i; - for (i = 0; i < 4; i += sizeof_s4DVertexPairRel) + size_t has_vertex_run; + for (has_vertex_run = 0; has_vertex_run < VertexCache.primitiveHasVertex; has_vertex_run += 1) { - v[i + 0].flag = (u32)(VertexCache.vSize[VertexCache.vType].Format); - v[i + 1].flag = v[i + 0].flag; + v[s4DVertex_ofs(has_vertex_run)].flag = (u32)(VertexCache.vSize[VertexCache.vType].Format); + v[s4DVertex_proj(has_vertex_run)].flag = v[s4DVertex_ofs(has_vertex_run)].flag; } - - size_t g; + size_t vOut; // vertices count per line - vOut = clipToFrustum (VertexCache.primitiveHasVertex); - if ( vOut < VertexCache.primitiveHasVertex) + vOut = clipToFrustum(VertexCache.primitiveHasVertex); + if (vOut < VertexCache.primitiveHasVertex) return; - vOut *= sizeof_s4DVertexPairRel; - // to DC Space, project homogenous vertex - ndc_2_dc_and_project ( v + 1, v, vOut ); + ndc_2_dc_and_project(v + s4DVertex_proj(0), v+ s4DVertex_ofs(0), s4DVertex_ofs(vOut)); // unproject vertex color #if 0 #if BURNING_MATERIAL_MAX_COLORS > 0 - for ( g = 0; g != vOut; g+= 2 ) + for (g = 0; g != vOut; g += 2) { - v[ g + 1].Color[0].setA8R8G8B8 ( color.color ); + v[g + 1].Color[0].setA8R8G8B8(color.color); } #endif #endif - IBurningShader * shader = 0; - if ( CurrentShader && CurrentShader->canWireFrame() ) shader = CurrentShader; - else shader = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; - shader = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; + IBurningShader* shader = 0; + if (CurrentShader && CurrentShader->canWireFrame()) shader = CurrentShader; + else shader = BurningShader[ETR_TEXTURE_GOURAUD_WIRE]; + shader = BurningShader[ETR_TEXTURE_GOURAUD_WIRE]; - shader->pushEdgeTest(1,0,1); - shader->setRenderTarget(RenderTargetSurface, ViewPort); + shader->pushEdgeTest(1, 0, 1); + shader->setRenderTarget(RenderTargetSurface, ViewPort, Interlaced); - for ( g = 0; g <= vOut - 4; g += sizeof_s4DVertexPairRel) + for (has_vertex_run = 0; (has_vertex_run + VertexCache.primitiveHasVertex) <= vOut; has_vertex_run += 1) { - shader->drawLine ( v + 1 + g, v + 1 + g + sizeof_s4DVertexPairRel); + shader->drawLine(v + s4DVertex_proj(has_vertex_run), v + s4DVertex_proj(has_vertex_run+1)); } shader->popEdgeTest(); @@ -3561,15 +3419,15 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const wchar_t* CBurningVideoDriver::getName() const { #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL - return L"Burning's Video 0.51 beautiful"; + return L"Burning's Video 0.52 beautiful"; #elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST ) - return L"Burning's Video 0.51 ultra fast"; + return L"Burning's Video 0.52 ultra fast"; #elif defined ( BURNINGVIDEO_RENDERER_FAST ) - return L"Burning's Video 0.51 fast"; + return L"Burning's Video 0.52 fast"; #elif defined ( BURNINGVIDEO_RENDERER_CE ) - return L"Burning's Video 0.51 CE"; + return L"Burning's Video 0.52 CE"; #else - return L"Burning's Video 0.51"; + return L"Burning's Video 0.52"; #endif } @@ -3590,16 +3448,22 @@ E_DRIVER_TYPE CBurningVideoDriver::getDriverType() const //! returns color format ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const { - return BURNINGSHADER_COLOR_FORMAT; + return BackBuffer ? BackBuffer->getColorFormat() : CNullDriver::getColorFormat(); } //! Creates a render target texture. ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, - const io::path& name, const ECOLOR_FORMAT format) + const io::path& name, const ECOLOR_FORMAT format +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + , const bool useStencil +#endif +) { - IImage* img = createImage(BURNINGSHADER_COLOR_FORMAT, size); - ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET,this); + //IImage* img = createImage(SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT, size); + //empty proxy image + IImage* img = createImageFromData(format, size, 0, true, false); + ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET /*| CSoftwareTexture2::GEN_MIPMAP */, this); img->drop(); addTexture(tex); tex->drop(); @@ -3608,14 +3472,9 @@ ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2dfill(color); - - if ((flag & ECBF_DEPTH) && DepthBuffer) - DepthBuffer->clear(depth); - - if ((flag & ECBF_STENCIL) && StencilBuffer) - StencilBuffer->clear(stencil); + if ((flag & ECBF_COLOR) && RenderTargetSurface) image_fill(RenderTargetSurface, color, Interlaced); + if ((flag & ECBF_DEPTH) && DepthBuffer) DepthBuffer->clear(depth, Interlaced); + if ((flag & ECBF_STENCIL) && StencilBuffer) StencilBuffer->clear(stencil, Interlaced); } #if 0 @@ -3657,8 +3516,12 @@ IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video ITexture* CBurningVideoDriver::createDeviceDependentTexture(const io::path& name, IImage* image) { u32 flags = - ((TextureCreationFlags & ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) + ((TextureCreationFlags & ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + | CSoftwareTexture2::GEN_MIPMAP_AUTO +#else | ((TextureCreationFlags & ETCF_AUTO_GENERATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP_AUTO : 0) +#endif | ((TextureCreationFlags & ETCF_ALLOW_NON_POWER_2) ? CSoftwareTexture2::ALLOW_NPOT : 0) #if defined(IRRLICHT_sRGB) | ((TextureCreationFlags & ETCF_IMAGE_IS_LINEAR) ? CSoftwareTexture2::IMAGE_IS_LINEAR : 0) @@ -3700,8 +3563,8 @@ void CBurningVideoDriver::drawStencilShadowVolume(const core::arraysetRenderTarget(RenderTargetSurface, ViewPort); - CurrentShader->pushEdgeTest(Material.org.Wireframe, 0,0); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort, Interlaced); + CurrentShader->pushEdgeTest(Material.org.Wireframe, 0, 0); //setMaterial EyeSpace.TL_Flag &= ~(TL_TEXTURE_TRANSFORM | TL_LIGHT0_IS_NORMAL_MAP); @@ -3717,15 +3580,15 @@ void CBurningVideoDriver::drawStencilShadowVolume(const core::arraysetStencilOp( StencilOp_KEEP, StencilOp_INCR, StencilOp_KEEP); - drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); + CurrentShader->setStencilOp(StencilOp_KEEP, StencilOp_INCR, StencilOp_KEEP); + drawVertexPrimitiveList(triangles.const_pointer(), count, 0, count / 3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); Material.org.BackfaceCulling = true; Material.org.FrontfaceCulling = false; Material.CullFlag = CULL_BACK | CULL_INVISIBLE; - CurrentShader->setStencilOp( StencilOp_KEEP, StencilOp_DECR, StencilOp_KEEP); - drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); + CurrentShader->setStencilOp(StencilOp_KEEP, StencilOp_DECR, StencilOp_KEEP); + drawVertexPrimitiveList(triangles.const_pointer(), count, 0, count / 3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); } else // zpass { @@ -3733,7 +3596,7 @@ void CBurningVideoDriver::drawStencilShadowVolume(const core::arraysetStencilOp( StencilOp_KEEP, StencilOp_KEEP, StencilOp_INCR); + CurrentShader->setStencilOp(StencilOp_KEEP, StencilOp_KEEP, StencilOp_INCR); drawVertexPrimitiveList(triangles.const_pointer(), count, 0, count / 3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); Material.org.BackfaceCulling = false; @@ -3755,59 +3618,62 @@ void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SCol { if (!StencilBuffer) return; + // draw a shadow rectangle covering the entire screen using stencil buffer const u32 h = RenderTargetSurface->getDimension().Height; const u32 w = RenderTargetSurface->getDimension().Width; - tVideoSample *dst; - const tStencilSample* stencil; -#if defined(SOFTWARE_DRIVER_2_32BIT) - const u32 alpha = extractAlpha(leftUpEdge.color); - const u32 src = leftUpEdge.color; -#else - const u16 alpha = extractAlpha( leftUpEdge.color ) >> 3; - const u32 src = video::A8R8G8B8toA1R5G5B5( leftUpEdge.color ); -#endif + const bool bit32 = RenderTargetSurface->getColorFormat() == ECF_A8R8G8B8; + const tVideoSample alpha = extractAlpha(leftUpEdge.color) >> (bit32 ? 0 : 3); + const tVideoSample src = bit32 ? leftUpEdge.color : video::A8R8G8B8toA1R5G5B5(leftUpEdge.color); - - for ( u32 y = 0; y < h; ++y ) + interlace_scanline_data line; + for (line.y = 0; line.y < h; line.y += SOFTWARE_DRIVER_2_STEP_Y) { - dst = (tVideoSample*)RenderTargetSurface->getData() + ( y * w ); - stencil = (tStencilSample*)StencilBuffer->lock() + (y * w); - - for ( u32 x = 0; x < w; ++x ) + interlace_scanline { - if ( stencil[x] ) + tVideoSample * dst = (tVideoSample*)RenderTargetSurface->getData() + (line.y * w); + const tStencilSample* stencil = (tStencilSample*)StencilBuffer->lock() + (line.y * w); + + if (bit32) { -#if defined(SOFTWARE_DRIVER_2_32BIT) - dst[x] = PixelBlend32 ( dst[x], src,alpha ); -#else - dst[x] = PixelBlend16( dst[x], src, alpha ); -#endif + for (u32 x = 0; x < w; x += SOFTWARE_DRIVER_2_STEP_X) + { + if (stencil[x]) dst[x] = PixelBlend32(dst[x], src, alpha); + } } + else + { + for (u32 x = 0; x < w; x += SOFTWARE_DRIVER_2_STEP_X) + { + if (stencil[x]) dst[x] = PixelBlend16(dst[x], src, alpha); + } + } + } } - if ( clearStencilBuffer ) - StencilBuffer->clear(0); + if (clearStencilBuffer) + StencilBuffer->clear(0, Interlaced); } core::dimension2du CBurningVideoDriver::getMaxTextureSize() const { - return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1 << 20, - SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1 << 20); + return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); } bool CBurningVideoDriver::queryTextureFormat(ECOLOR_FORMAT format) const { - return format == BURNINGSHADER_COLOR_FORMAT; + return format == SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT || format == SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT; } +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) bool CBurningVideoDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const { return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation(); // || material.isTransparent(); } +#endif s32 CBurningVideoDriver::addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, @@ -3847,7 +3713,7 @@ s32 CBurningVideoDriver::addHighLevelShaderMaterial( IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData - ) +) { s32 materialID = -1; @@ -3949,11 +3815,11 @@ namespace video //! creates a video driver IVideoDriver* createBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter) { - #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ - return new CBurningVideoDriver(params, io, presenter); - #else - return 0; - #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + return new CBurningVideoDriver(params, io, presenter); +#else + return 0; +#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } diff --git a/source/Irrlicht/CSoftwareDriver2.h b/source/Irrlicht/CSoftwareDriver2.h index 803deae6..4c87bf3f 100644 --- a/source/Irrlicht/CSoftwareDriver2.h +++ b/source/Irrlicht/CSoftwareDriver2.h @@ -50,6 +50,18 @@ namespace video virtual bool beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect* sourceRect) _IRR_OVERRIDE_; +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + virtual bool beginScene(bool backBuffer, bool zBuffer, SColor color, + const SExposedVideoData& videoData, core::rect* sourceRect) + { + u16 flag = 0; + if (backBuffer) flag |= ECBF_COLOR; + if (zBuffer) flag |= ECBF_DEPTH; + return beginScene(flag, color, 1.f, 0, videoData, sourceRect); + } + virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); +#endif + virtual bool endScene() _IRR_OVERRIDE_; //! Only used by the internal engine. Used to notify the driver that @@ -152,7 +164,12 @@ namespace video //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN) _IRR_OVERRIDE_; + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + , const bool useStencil = false +#endif + ) _IRR_OVERRIDE_; + virtual void clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) _IRR_OVERRIDE_; @@ -190,8 +207,10 @@ namespace video //! Check if the driver supports creating textures with the given color format virtual bool queryTextureFormat(ECOLOR_FORMAT format) const _IRR_OVERRIDE_; +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) //! Used by some SceneNodes to check if a material should be rendered in the transparent render pass virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_; +#endif IDepthBuffer * getDepthBuffer () { return DepthBuffer; } IStencilBuffer * getStencilBuffer () { return StencilBuffer; } @@ -252,6 +271,33 @@ namespace video virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) _IRR_OVERRIDE_; +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), floats, count); + } + virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), (const s32*)bools, count); + } + virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), ints, count); + } + + virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), floats, count); + } + virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), (const s32*)bools, count); + } + virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), ints, count); + } +#endif //! Get pointer to the IVideoDriver interface /** \return Pointer to the IVideoDriver interface */ virtual IVideoDriver* getVideoDriver() _IRR_OVERRIDE_; @@ -261,7 +307,7 @@ namespace video void saveBuffer(); //! sets a render target - void setRenderTargetImage(video::CImage* image); + void setRenderTargetImage2(video::IImage* color, video::IImage* depth=0, video::IImage* stencil=0); //! sets the current Texture //bool setTexture(u32 stage, video::ITexture* texture); @@ -278,6 +324,7 @@ namespace video video::ITexture* RenderTargetTexture; video::IImage* RenderTargetSurface; core::dimension2d RenderTargetSize; + sVec4 RatioRenderTargetScreen; // Smaller Render Target IBurningShader* CurrentShader; IBurningShader* BurningShader[ETR2_COUNT]; @@ -302,6 +349,8 @@ namespace video ETS_COUNT_BURNING = 16 }; + // align manually to 16 byte start address + //u8 _pack_0[8]; enum E_TRANSFORMATION_FLAG { ETF_VALID = 1, @@ -311,12 +360,12 @@ namespace video ETF_TEXGEN_WRAP = 16, ETF_TEXGEN_MASK = ETF_TEXGEN_CAMERA_SPHERE | ETF_TEXGEN_CAMERA_REFLECTION | ETF_TEXGEN_WRAP }; - core::matrix4 Transformation[2][ETS_COUNT_BURNING]; - size_t TransformationFlag[2][ETS_COUNT_BURNING]; // E_TRANSFORMATION_FLAG - size_t TransformationStack; // 0 .. 3D , 1 .. 2D + core::matrix4 ALIGN(16) Transformation[2][ETS_COUNT_BURNING]; + size_t TransformationFlag[2][ETS_COUNT_BURNING]; // E_TRANSFORMATION_FLAG + - void setRenderStates2DMode(const video::SColor& color,video::ITexture* texture,bool useAlphaChannelOfTexture); + void setRenderStates2DMode(const video::SColor& color,const video::ITexture* texture,bool useAlphaChannelOfTexture); void setRenderStates3DMode(); //ETS_CLIPSCALE, // moved outside to stay at 16 matrices @@ -366,7 +415,7 @@ namespace video //const is misleading. **v is const that true, but not *v.. f32 screenarea_inside (const s4DVertexPair* burning_restrict const face[] ) const; - s32 lodFactor_inside ( const s4DVertexPair* burning_restrict const face[], const size_t tex, f32 dc_area, f32 lod_bias ) const; + s32 lodFactor_inside ( const s4DVertexPair* burning_restrict const face[], const size_t tex, const f32 dc_area, const f32 lod_bias ) const; void select_polygon_mipmap_inside ( s4DVertex* burning_restrict face[], const size_t tex, const CSoftwareTexture2_Bound& b ) const; void getCameraPosWorldSpace(); @@ -377,6 +426,20 @@ namespace video //! Built-in 2D quad for 2D rendering. S3DVertex Quad2DVertices[4]; + interlaced_control Interlaced; + +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + core::array RenderTargets; + + inline bool getWriteZBuffer(const SMaterial& material) const + { + return material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent()); + } + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData = 0) + { + return createDeviceDependentTexture(name, surface); + } +#endif }; diff --git a/source/Irrlicht/CSoftwareTexture2.cpp b/source/Irrlicht/CSoftwareTexture2.cpp index 29febe1e..2da1baa7 100644 --- a/source/Irrlicht/CSoftwareTexture2.cpp +++ b/source/Irrlicht/CSoftwareTexture2.cpp @@ -20,6 +20,30 @@ namespace video //! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB) void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect* dstRect, const video::IImage* src, const core::rect* srcRect, size_t flags); +//nearest pow of 2 ( 257 will be 256 not 512 ) +static inline core::dimension2d getOptimalSize(const core::dimension2d& original, const u32 allowNonPowerOfTwo, const u32 maxSize) +{ + u32 w, h; + if (allowNonPowerOfTwo) + { + w = original.Width; + h = original.Height; + } + else + { + w = 1; + while (w * 2 < original.Width) w *= 2; + if (w * 2 - original.Width < original.Width - w) w *= 2; + + h = 1; + while (h * 2 < original.Height) h *= 2; + if (h * 2 - original.Height < original.Height - h) h *= 2; + } + if (maxSize && w > maxSize) w = maxSize; + if (maxSize && h > maxSize) h = maxSize; + return core::dimension2d(w, h); +} + //! constructor CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags, CBurningVideoDriver* driver) : ITexture(name @@ -27,24 +51,24 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl , ETT_2D #endif ) - ,MipMapLOD(0), Flags(flags), Driver(driver) + , MipMapLOD(0), Flags(flags), Driver(driver) { - #ifdef _DEBUG +#ifdef _DEBUG setDebugName("CSoftwareTexture2"); - #endif +#endif -#ifndef SOFTWARE_DRIVER_2_MIPMAPPING - Flags &= ~(GEN_MIPMAP| GEN_MIPMAP_AUTO); +#if SOFTWARE_DRIVER_2_MIPMAPPING_MAX <= 1 + Flags &= ~(GEN_MIPMAP | GEN_MIPMAP_AUTO); #endif //set baseclass properties DriverType = EDT_BURNINGSVIDEO; - ColorFormat = BURNINGSHADER_COLOR_FORMAT; + ColorFormat = (Flags & IS_RENDERTARGET) ? SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT : SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT; IsRenderTarget = (Flags & IS_RENDERTARGET) != 0; HasMipMaps = (Flags & GEN_MIPMAP) != 0; MipMap0_Area[0] = 1; MipMap0_Area[1] = 1; - LodBIAS = 0.75f; - for ( size_t i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) MipMap[i] = 0; + LodBIAS = 1.f; + for (size_t i = 0; i < array_size(MipMap); ++i) MipMap[i] = 0; if (!image) return; OriginalSize = image->getDimension(); @@ -52,7 +76,7 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl #if defined(IRRLICHT_sRGB) - if ( Flags & IMAGE_IS_LINEAR ) image->set_sRGB(0); + if (Flags & IMAGE_IS_LINEAR) image->set_sRGB(0); #else //guessing linear image if (name.find("light") >= 0 || @@ -72,47 +96,65 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl //visual studio code warning u32 maxTexSize = SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE; - core::dimension2d optSize( OriginalSize.getOptimalSize( + +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + if (IsRenderTarget && name.find("RaceGUI::markers") >= 0) + { + maxTexSize = 0; + } +#endif + /* + core::dimension2d optSize(OriginalSize.getOptimalSize( (Flags & ALLOW_NPOT) ? 0 : 1, // requirePowerOfTwo false, // requireSquare - (Flags & ALLOW_NPOT) ? 1 : maxTexSize == 0, // larger + (Flags & ALLOW_NPOT) ? 1 : maxTexSize == SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, // larger (Flags & ALLOW_NPOT) ? 0 : maxTexSize // maxValue ) - ); - + ); + */ + core::dimension2d optSize(getOptimalSize(OriginalSize, Flags & ALLOW_NPOT, maxTexSize)); if (OriginalSize == optSize) { - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); + MipMap[0] = new CImage(ColorFormat, image->getDimension()); #if defined(IRRLICHT_sRGB) - MipMap[0]->set_sRGB( (Flags & TEXTURE_IS_LINEAR ) ? 0 : image->get_sRGB() ); + MipMap[0]->set_sRGB((Flags & TEXTURE_IS_LINEAR) ? 0 : image->get_sRGB()); #endif - if (!isCompressed) + if (!isCompressed && image->getData()) image->copyTo(MipMap[0]); } else { - char buf[256]; - core::stringw showName ( name ); - snprintf_irr ( buf, sizeof(buf), "Burningvideo: Warning Texture %ls reformat %ux%u,%d -> %ux%u,%d", - showName.c_str(), - OriginalSize.Width, OriginalSize.Height, OriginalColorFormat, - optSize.Width, optSize.Height,BURNINGSHADER_COLOR_FORMAT - ); - - os::Printer::log ( buf, ELL_WARNING ); - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); + MipMap[0] = new CImage(ColorFormat, optSize); #if defined(IRRLICHT_sRGB) - MipMap[0]->set_sRGB( (Flags & TEXTURE_IS_LINEAR ) ? 0 : image->get_sRGB() ); + MipMap[0]->set_sRGB((Flags & TEXTURE_IS_LINEAR) ? 0 : image->get_sRGB()); #endif if (!isCompressed) { //image->copyToScalingBoxFilter ( MipMap[0],0, false ); - Resample_subSampling(BLITTER_TEXTURE,MipMap[0],0,image,0, Flags); + Resample_subSampling(BLITTER_TEXTURE, MipMap[0], 0, image, 0, Flags); } // if Original Size is used for calculation ( 2D position, font) it will be wrong //OriginalSize = optSize; } + // Show Information about resizing + if (OriginalSize != optSize || + ( OriginalColorFormat != ColorFormat && + !((OriginalColorFormat == ECF_R8G8B8 || OriginalColorFormat == ECF_A1R5G5B5) && ColorFormat == ECF_A8R8G8B8) + ) + ) + { + char buf[256]; + core::stringw showName(name); + snprintf_irr(buf, sizeof(buf), "Burningvideo: Texture '%ls' reformat %ux%u,%s -> %ux%u,%s", + showName.c_str(), + OriginalSize.Width, OriginalSize.Height, ColorFormatNames[OriginalColorFormat], + optSize.Width, optSize.Height, ColorFormatNames[ColorFormat] + ); + os::Printer::log(buf, ELL_DEBUG); + } + + //select highest mipmap 0 regenerateMipMapLevels(image->getMipMapsData()); } @@ -121,9 +163,9 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl //! destructor CSoftwareTexture2::~CSoftwareTexture2() { - for ( size_t i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + for (size_t i = 0; i < array_size(MipMap); ++i) { - if ( MipMap[i] ) + if (MipMap[i]) { MipMap[i]->drop(); MipMap[i] = 0; @@ -132,7 +174,6 @@ CSoftwareTexture2::~CSoftwareTexture2() } - //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture #if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) @@ -141,12 +182,12 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) void CSoftwareTexture2::regenerateMipMapLevels(void* data) #endif { - int i; + size_t i; // release - for ( i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + for (i = 1; i < array_size(MipMap); ++i) { - if ( MipMap[i] ) + if (MipMap[i]) { MipMap[i]->drop(); MipMap[i] = 0; @@ -155,10 +196,10 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) core::dimension2d newSize; - if (HasMipMaps && ( (Flags & GEN_MIPMAP_AUTO) || 0 == data ) ) + if (HasMipMaps && ((Flags & GEN_MIPMAP_AUTO) || 0 == data)) { //need memory also if autogen mipmap disabled - for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + for (i = 1; i < array_size(MipMap); ++i) { const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); //isotropic @@ -167,7 +208,7 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) if (upperDim == newSize) break; - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + MipMap[i] = new CImage(ColorFormat, newSize); #if defined(IRRLICHT_sRGB) MipMap[i]->set_sRGB(MipMap[i - 1]->get_sRGB()); #endif @@ -192,13 +233,13 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) if (origSize.Height > 1) origSize.Height >>= 1; mip_end += IImage::getDataSizeFromFormat(OriginalColorFormat, origSize.Width, origSize.Height); i += 1; - } while ((origSize.Width != 1 || origSize.Height != 1) && i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX); + } while ((origSize.Width != 1 || origSize.Height != 1) && i < array_size(MipMap)); //TODO: this is not true - LodBIAS = i*0.75f; + LodBIAS = i * 2.f; origSize = OriginalSize; - for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX && mip_current < mip_end; ++i) + for (i = 1; i < array_size(MipMap) && mip_current < mip_end; ++i) { const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); //isotropic @@ -210,10 +251,10 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) if (origSize.Width > 1) origSize.Width >>= 1; if (origSize.Height > 1) origSize.Height >>= 1; - if (OriginalColorFormat != BURNINGSHADER_COLOR_FORMAT) + if (OriginalColorFormat != ColorFormat) { IImage* tmpImage = new CImage(OriginalColorFormat, origSize, mip_current, true, false); - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + MipMap[i] = new CImage(ColorFormat, newSize); if (origSize == newSize) tmpImage->copyTo(MipMap[i]); else @@ -223,11 +264,11 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) else { if (origSize == newSize) - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mip_current, false); + MipMap[i] = new CImage(ColorFormat, newSize, mip_current, false); else { - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mip_current, true, false); + MipMap[i] = new CImage(ColorFormat, newSize); + IImage* tmpImage = new CImage(ColorFormat, origSize, mip_current, true, false); tmpImage->copyToScalingBoxFilter(MipMap[i]); tmpImage->drop(); } @@ -238,33 +279,33 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) //visualize mipmap - for (i=1; i < 0 && i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + for (i = 1; i < 0 && i < array_size(MipMap); ++i) { -/* static u32 color[] = { - 0x30bf7f00,0x3040bf00,0x30bf00bf,0x3000bf00, - 0x300080bf,0x30bf4000,0x300040bf,0x307f00bf, - 0x30bf0000,0x3000bfbf,0x304000bf,0x307fbf00, - 0x8000bf7f,0x80bf0040,0x80bfbf00,0x800000bf - }; -*/ - static u32 color[] = { - 0xFFFFFFFF,0xFFFF0000,0xFF00FF00,0xFF0000FF, - 0xFFFFFF00,0xFF00FFFF,0xFFFF00FF,0xFF0000FF, - 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFF0000FF, - 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFFFF00FF + 0xFFFF0000, + 0xFFFF0000,0xFF00FF00,0xFF0000FF, + 0xFFFFFF00,0xFF00FFFF,0xFFFF00FF, + 0xFFff6600,0xFF00ff66,0xFF6600FF, + 0xFF66ff00,0xFF0066ff,0xFFff0066, + 0xFF33ff00,0xFF0033ff,0xFF3300ff, + 0xFF0000FF,0xFF0000FF,0xFF0000FF }; - if ( MipMap[i] ) + if (MipMap[i]) { - core::rect p (core::position2di(0,0),MipMap[i]->getDimension()); + int border = 0; + const core::dimension2du& d = MipMap[i]->getDimension(); + core::rect p(0, 0, d.Width, d.Height); SColor c((color[i & 15] & 0x00FFFFFF) | 0xFF000000); - Blit(BLITTER_TEXTURE_ALPHA_COLOR_BLEND, MipMap[i], 0, 0, MipMap[i], &p, c.color); + + core::rect dclip(border, border, d.Width - border, d.Height - border); + + Blit(BLITTER_TEXTURE_ALPHA_COLOR_BLEND, MipMap[i], &dclip, 0, MipMap[i], &p, c.color); } } //save mipmap chain - if ( 0 ) + if (0) { char buf[256]; const char* name = getName().getPath().c_str(); @@ -273,15 +314,15 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data) i = 0; while (name[i]) { - if (name[i] == '/' || name[i] == '\\') filename = i + 1; + if (name[i] == '/' || name[i] == '\\') filename = (s32)i + 1; //if (name[i] == '.') ext = i; i += 1; } - for (i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + for (i = 0; i < array_size(MipMap); ++i) { if (MipMap[i]) { - snprintf_irr(buf, sizeof(buf),"mip/%s_%02d.png", name + filename,i); + snprintf_irr(buf, sizeof(buf), "mip/%s_%02d.png", name + filename, (s32)i); Driver->writeImageToFile(MipMap[i], buf); } } @@ -300,12 +341,16 @@ void CSoftwareTexture2::calcDerivative() MipMap0_Area[0] = dim.Width; MipMap0_Area[1] = dim.Height; // screensize of a triangle + //TA: try to mimic openGL mipmap. ( don't do this!) + //if (MipMap0_Area[0] < 32) MipMap0_Area[0] = 32; + //if (MipMap0_Area[1] < 32) MipMap0_Area[1] = 32; + Size = dim; // MipMap[MipMapLOD]->getDimension(); Pitch = MipMap[MipMapLOD]->getPitch(); } //preCalc mipmap texel center boundaries - for ( s32 i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + for (size_t i = 0; i < array_size(MipMap); ++i) { CSoftwareTexture2_Bound& b = TexBound[i]; if (MipMap[i]) @@ -335,7 +380,7 @@ void CSoftwareTexture2::calcDerivative() CSoftwareRenderTarget2::CSoftwareRenderTarget2(CBurningVideoDriver* driver) : Driver(driver) #if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) -, IRenderTarget(0) + , IRenderTarget(0) #endif { DriverType = EDT_BURNINGSVIDEO; @@ -378,12 +423,6 @@ void CSoftwareRenderTarget2::setTexture(const core::array& texture, I } } -ITexture* CSoftwareRenderTarget2::getTexture() const -{ - return Texture[0]; -} - - static const float srgb_8bit_to_linear_float[1 << 8] = { 0.0f, 3.03527e-4f, 6.07054e-4f, 9.10581e-4f, @@ -474,7 +513,7 @@ u32 linear_to_srgb_8bit(const float v) ieee754 c; c.f = v; const size_t x = c.u; - const u32 *table = (u32*)srgb_8bit_to_linear_float; + const u32* table = (u32*)srgb_8bit_to_linear_float; u32 y = 0; y += table[y + 128] <= x ? 128 : 0; y += table[y + 64] <= x ? 64 : 0; @@ -497,7 +536,7 @@ struct absrect2 s32 y1; }; -static inline int clipTest(absrect2 &o, const core::rect* a, const absrect2& b) +static inline int clipTest(absrect2& o, const core::rect* a, const absrect2& b) { if (a == 0) { @@ -522,19 +561,19 @@ static inline int clipTest(absrect2 &o, const core::rect* a, const absrect2 //! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB) // todo: texture jumps (mip selection problem) void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect* dstRect, - const video::IImage* src, const core::rect* srcRect,size_t flags) + const video::IImage* src, const core::rect* srcRect, size_t flags) { + u8* dstData = (u8*)dst->getData(); const absrect2 dst_clip = { 0,0,(s32)dst->getDimension().Width,(s32)dst->getDimension().Height }; absrect2 dc; - if (clipTest(dc, dstRect, dst_clip)) return; + if (clipTest(dc, dstRect, dst_clip) || !dstData) return; const video::ECOLOR_FORMAT dstFormat = dst->getColorFormat(); - u8* dstData = (u8*)dst->getData(); + const u8* srcData = (u8*)src->getData(); const absrect2 src_clip = { 0,0,(s32)src->getDimension().Width,(s32)src->getDimension().Height }; absrect2 sc; - if (clipTest(sc, srcRect, src_clip)) return; + if (clipTest(sc, srcRect, src_clip) || !srcData) return; const video::ECOLOR_FORMAT srcFormat = src->getColorFormat(); - const u8* srcData = (u8*)src->getData(); #if defined(IRRLICHT_sRGB) const int dst_sRGB = dst->get_sRGB(); @@ -560,14 +599,14 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect for (int dy = dc.y0; dy < dc.y1; ++dy) { f[1] = f[3]; - f[3] = sc.y0 + (dy + 1 - dc.y0)*scale[1]; + f[3] = sc.y0 + (dy + 1 - dc.y0) * scale[1]; if (f[3] >= sc.y1) f[3] = sc.y1 - 0.001f; //todo:1.f/dim should be enough f[2] = (float)sc.x0; for (int dx = dc.x0; dx < dc.x1; ++dx) { f[0] = f[2]; - f[2] = sc.x0 + (dx + 1 - dc.x0)*scale[0]; + f[2] = sc.x0 + (dx + 1 - dc.x0) * scale[0]; if (f[2] >= sc.x1) f[2] = sc.x1 - 0.001f; //accumulate linear color @@ -599,12 +638,12 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect switch (srcFormat) { - case video::ECF_A1R5G5B5: sbgra = video::A1R5G5B5toA8R8G8B8(*(u16*)(srcData + (fy*src_clip.x1) * 2 + (fx * 2))); break; - case video::ECF_R5G6B5: sbgra = video::R5G6B5toA8R8G8B8(*(u16*)(srcData + (fy*src_clip.x1) * 2 + (fx * 2))); break; - case video::ECF_A8R8G8B8: sbgra = *(u32*)(srcData + (fy*src_clip.x1) * 4 + (fx * 4)); break; + case video::ECF_A1R5G5B5: sbgra = video::A1R5G5B5toA8R8G8B8(*(u16*)(srcData + (fy * src_clip.x1) * 2 + (fx * 2))); break; + case video::ECF_R5G6B5: sbgra = video::R5G6B5toA8R8G8B8(*(u16*)(srcData + (fy * src_clip.x1) * 2 + (fx * 2))); break; + case video::ECF_A8R8G8B8: sbgra = *(u32*)(srcData + (fy * src_clip.x1) * 4 + (fx * 4)); break; case video::ECF_R8G8B8: { - const u8* p = srcData + (fy*src_clip.x1) * 3 + (fx * 3); + const u8* p = srcData + (fy * src_clip.x1) * 3 + (fx * 3); sbgra = 0xFF000000 | p[0] << 16 | p[1] << 8 | p[2]; } break; default: break; @@ -650,16 +689,16 @@ void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect } switch (dstFormat) { - case video::ECF_A8R8G8B8: *(u32*)(dstData + (dy*dst_clip.x1) * 4 + (dx * 4)) = sbgra; break; + case video::ECF_A8R8G8B8: *(u32*)(dstData + (dy * dst_clip.x1) * 4 + (dx * 4)) = sbgra; break; case video::ECF_R8G8B8: { - u8* p = dstData + (dy*dst_clip.x1) * 3 + (dx * 3); + u8* p = dstData + (dy * dst_clip.x1) * 3 + (dx * 3); p[2] = (sbgra) & 0xFF; p[1] = (sbgra >> 8) & 0xFF; p[0] = (sbgra >> 16) & 0xFF; } break; - case video::ECF_A1R5G5B5: *(u16*)(dstData + (dy*dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toA1R5G5B5(sbgra); break; - case video::ECF_R5G6B5: *(u16*)(dstData + (dy*dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toR5G6B5(sbgra); break; + case video::ECF_A1R5G5B5: *(u16*)(dstData + (dy * dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toA1R5G5B5(sbgra); break; + case video::ECF_R5G6B5: *(u16*)(dstData + (dy * dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toR5G6B5(sbgra); break; default: break; } diff --git a/source/Irrlicht/CSoftwareTexture2.h b/source/Irrlicht/CSoftwareTexture2.h index 4f6be486..37bd1c7d 100644 --- a/source/Irrlicht/CSoftwareTexture2.h +++ b/source/Irrlicht/CSoftwareTexture2.h @@ -8,7 +8,11 @@ #include "SoftwareDriver2_compile_config.h" #include "ITexture.h" +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) +#include "IVideoDriver.h" +#else #include "IRenderTarget.h" +#endif #include "CImage.h" namespace irr @@ -51,14 +55,18 @@ public: u32 getMipmapLevel(s32 newLevel) const { if ( newLevel < 0 ) newLevel = 0; - else if ( newLevel >= SOFTWARE_DRIVER_2_MIPMAPPING_MAX ) newLevel = SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1; + else if ( newLevel >= (s32)array_size(MipMap)) newLevel = array_size(MipMap) - 1; while ( newLevel > 0 && MipMap[newLevel] == 0 ) newLevel -= 1; return newLevel; } //! lock function +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + virtual void* lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) +#else virtual void* lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) _IRR_OVERRIDE_ +#endif { if (Flags & GEN_MIPMAP) { @@ -75,18 +83,20 @@ public: virtual void unlock() _IRR_OVERRIDE_ { } - +/* //! compare the area drawn with the area of the texture f32 getLODFactor( const f32 texArea ) const { return MipMap0_Area[0]* MipMap0_Area[1] * 0.5f * texArea; //return MipMap[0]->getImageDataSizeInPixels () * texArea; } +*/ const u32* getMipMap0_Area() const { return MipMap0_Area; } + f32 get_lod_bias() const { return LodBIAS; } //! returns unoptimized surface (misleading name. burning can scale down originalimage) virtual CImage* getImage() const @@ -106,9 +116,33 @@ public: return TexBound[MipMapLOD]; } +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_; +#else + virtual void regenerateMipMapLevels(void* data = 0); +#endif + + +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + const core::dimension2d& getOriginalSize() const { return OriginalSize; }; + const core::dimension2d& getSize() const { return Size; }; + E_DRIVER_TYPE getDriverType() const { return DriverType; }; + ECOLOR_FORMAT getColorFormat() const { return ColorFormat; }; + ECOLOR_FORMAT getOriginalColorFormat() const { return OriginalColorFormat; }; + u32 getPitch() const { return Pitch; }; + bool hasMipMaps() const { return HasMipMaps; } + bool isRenderTarget() const { return IsRenderTarget; } + + core::dimension2d OriginalSize; + core::dimension2d Size; + E_DRIVER_TYPE DriverType; + ECOLOR_FORMAT OriginalColorFormat; + ECOLOR_FORMAT ColorFormat; + u32 Pitch; + bool HasMipMaps; + bool IsRenderTarget; +#endif - f32 get_lod_bias() const { return LodBIAS; } private: void calcDerivative(); @@ -120,7 +154,7 @@ private: CImage* MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; CSoftwareTexture2_Bound TexBound[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; u32 MipMap0_Area[2]; - f32 LodBIAS; + f32 LodBIAS; // Tweak mipmap selection }; /*! @@ -134,7 +168,10 @@ public: virtual void setTexture(const core::array& texture, ITexture* depthStencil, const core::array& cubeSurfaces) _IRR_OVERRIDE_; - ITexture* getTexture() const; +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + E_DRIVER_TYPE DriverType; + core::array Texture; +#endif protected: CBurningVideoDriver* Driver; diff --git a/source/Irrlicht/CTRGouraud2.cpp b/source/Irrlicht/CTRGouraud2.cpp index d0488b57..5558f061 100644 --- a/source/Irrlicht/CTRGouraud2.cpp +++ b/source/Irrlicht/CTRGouraud2.cpp @@ -87,7 +87,7 @@ public: //virtual bool canWireFrame () { return true; } protected: - virtual void scanline_bilinear (); + virtual void fragmentShader(); }; @@ -104,7 +104,7 @@ CTRGouraud2::CTRGouraud2(CBurningVideoDriver* driver) /*! */ -void CTRGouraud2::scanline_bilinear () +void CTRGouraud2::fragmentShader() { tVideoSample *dst; @@ -143,7 +143,7 @@ void CTRGouraud2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -196,10 +196,11 @@ void CTRGouraud2::scanline_bilinear () #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { //if test active only first pixel - if ( (0 == EdgeTestPass) & i ) break; + if ((0 == EdgeTestPass) & (i > line.x_edgetest)) break; + #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif @@ -384,8 +385,9 @@ void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVer #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -416,7 +418,7 @@ void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVer #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; @@ -511,7 +513,6 @@ void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVer yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -545,8 +546,9 @@ void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVer #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -577,7 +579,7 @@ void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVer #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; diff --git a/source/Irrlicht/CTRGouraudAlpha2.cpp b/source/Irrlicht/CTRGouraudAlpha2.cpp index dd425f8b..7fc27e30 100644 --- a/source/Irrlicht/CTRGouraudAlpha2.cpp +++ b/source/Irrlicht/CTRGouraudAlpha2.cpp @@ -88,7 +88,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; @@ -105,7 +105,7 @@ CTRGouraudAlpha2::CTRGouraudAlpha2(CBurningVideoDriver* driver) /*! */ -void CTRGouraudAlpha2::scanline_bilinear () +void CTRGouraudAlpha2::fragmentShader() { tVideoSample *dst; @@ -148,7 +148,7 @@ void CTRGouraudAlpha2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -204,7 +204,7 @@ void CTRGouraudAlpha2::scanline_bilinear () tFixPoint r2, g2, b2; #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -270,9 +270,9 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -397,7 +397,7 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -428,7 +428,7 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // render a scanline - scanline_bilinear ( ); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -522,7 +522,6 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -557,7 +556,7 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -588,7 +587,7 @@ void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // render a scanline - scanline_bilinear ( ); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp index d921cb03..08b798a8 100644 --- a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp +++ b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp @@ -88,7 +88,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; //! constructor @@ -104,7 +104,7 @@ CTRGouraudAlphaNoZ2::CTRGouraudAlphaNoZ2(CBurningVideoDriver* driver) /*! */ -void CTRGouraudAlphaNoZ2::scanline_bilinear () +void CTRGouraudAlphaNoZ2::fragmentShader() { tVideoSample *dst; @@ -144,7 +144,7 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -201,7 +201,7 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () tFixPoint r2, g2, b2; #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -271,9 +271,9 @@ void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, cons const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -397,7 +397,7 @@ void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, cons #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -428,7 +428,7 @@ void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, cons #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -557,7 +557,7 @@ void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, cons #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -588,7 +588,7 @@ void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, cons #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRGouraudNoZ2.cpp b/source/Irrlicht/CTRGouraudNoZ2.cpp index 2e0bc393..b7201832 100644 --- a/source/Irrlicht/CTRGouraudNoZ2.cpp +++ b/source/Irrlicht/CTRGouraudNoZ2.cpp @@ -87,7 +87,7 @@ public: virtual bool canWireFrame () { return true; } protected: - virtual void scanline_bilinear (); + virtual void fragmentShader(); }; //! constructor @@ -103,7 +103,7 @@ CTRGouraudNoZ2::CTRGouraudNoZ2(CBurningVideoDriver* driver) /*! */ -void CTRGouraudNoZ2::scanline_bilinear () +void CTRGouraudNoZ2::fragmentShader() { tVideoSample *dst; @@ -142,7 +142,7 @@ void CTRGouraudNoZ2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -195,9 +195,9 @@ void CTRGouraudNoZ2::scanline_bilinear () #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { - if ( (0 == EdgeTestPass) & i ) break; + if ((0 == EdgeTestPass) & (i > line.x_edgetest)) break; #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -383,8 +383,10 @@ void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4D #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); + // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -415,7 +417,7 @@ void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4D #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; @@ -509,7 +511,6 @@ void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4D yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -542,9 +543,10 @@ void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4D #endif #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -575,7 +577,7 @@ void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4D #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; diff --git a/source/Irrlicht/CTRNormalMap.cpp b/source/Irrlicht/CTRNormalMap.cpp index 5df81c7a..5b16d083 100644 --- a/source/Irrlicht/CTRNormalMap.cpp +++ b/source/Irrlicht/CTRNormalMap.cpp @@ -164,7 +164,7 @@ void CTRNormalMap::fragmentShader() return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -254,7 +254,7 @@ void CTRNormalMap::fragmentShader() #endif - for ( s32 i = 0; i <= dx; i++ ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -400,9 +400,9 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -572,7 +572,7 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -618,7 +618,7 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe #endif // render a scanline - fragmentShader (); + interlace_scanline fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -751,7 +751,6 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -801,7 +800,7 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -847,7 +846,7 @@ void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVe #endif // render a scanline - fragmentShader(); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRStencilShadow.cpp b/source/Irrlicht/CTRStencilShadow.cpp index 82b5ed3d..81e64d63 100644 --- a/source/Irrlicht/CTRStencilShadow.cpp +++ b/source/Irrlicht/CTRStencilShadow.cpp @@ -139,7 +139,7 @@ void CTRStencilShadow::fragmentShader() SOFTWARE_DRIVER_2_CLIPCHECK; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -174,7 +174,7 @@ void CTRStencilShadow::fragmentShader() #endif s32 i; - for (i = 0; i <= dx; i++) + for (i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if (line.z[0] < z[i]) @@ -226,9 +226,9 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -382,7 +382,7 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -423,7 +423,7 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // render a scanline - fragmentShader (); + interlace_scanline fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -545,7 +545,6 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -590,7 +589,7 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -631,7 +630,7 @@ void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s #endif // render a scanline - fragmentShader (); + interlace_scanline fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureBlend.cpp b/source/Irrlicht/CTRTextureBlend.cpp index da178eb1..8d22291c 100644 --- a/source/Irrlicht/CTRTextureBlend.cpp +++ b/source/Irrlicht/CTRTextureBlend.cpp @@ -87,22 +87,6 @@ namespace video virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; -#if defined(PATCH_SUPERTUX_8_0_1) - - virtual void setZCompareFunc(u32 func) - { - depth_func = (E_COMPARISON_FUNC)func; - } - virtual void setParam(u32 index, f32 value) - { - SBurningShaderMaterial material; - material.org.ZBuffer = depth_func; - material.org.MaterialTypeParam = value; - OnSetMaterial(material); - } - -#endif - private: // fragment shader typedef void (CTRTextureBlend::*tFragmentShader) (); @@ -269,7 +253,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -325,7 +309,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -368,7 +352,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -454,7 +438,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -514,7 +498,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -561,7 +545,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -649,7 +633,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() return; // slopes - const f32 invDeltaX = reciprocal_zero2 ( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -707,7 +691,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -757,7 +741,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -850,7 +834,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -908,7 +892,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -957,7 +941,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -1050,7 +1034,7 @@ void CTRTextureBlend::fragment_src_alpha_one () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1108,7 +1092,7 @@ void CTRTextureBlend::fragment_src_alpha_one () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -1174,7 +1158,7 @@ void CTRTextureBlend::fragment_src_alpha_one () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -1280,7 +1264,7 @@ void CTRTextureBlend::fragment_src_alpha_one_minus_src_alpha() return; // slopes - const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + const f32 invDeltaX = fill_step_x(line.x[1] - line.x[0]); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1337,7 +1321,7 @@ void CTRTextureBlend::fragment_src_alpha_one_minus_src_alpha() { default: case ECFN_LESSEQUAL: - for (i = 0; i <= dx; ++i) + for (i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if (line.w[0] >= z[i]) @@ -1434,7 +1418,7 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1492,7 +1476,7 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -1541,7 +1525,7 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -1633,7 +1617,7 @@ void CTRTextureBlend::fragment_dst_color_zero () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1691,7 +1675,7 @@ void CTRTextureBlend::fragment_dst_color_zero () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -1739,7 +1723,7 @@ void CTRTextureBlend::fragment_dst_color_zero () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -1830,7 +1814,7 @@ void CTRTextureBlend::fragment_dst_color_one () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1888,7 +1872,7 @@ void CTRTextureBlend::fragment_dst_color_one () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -1937,7 +1921,7 @@ void CTRTextureBlend::fragment_dst_color_one () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -2030,7 +2014,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -2088,7 +2072,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () { default: case ECFN_LESSEQUAL: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] >= z[i] ) @@ -2137,7 +2121,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () break; case 2: - for ( i = 0; i <= dx; ++i ) + for ( i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_W if ( line.w[0] == z[i] ) @@ -2202,9 +2186,9 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -2328,7 +2312,7 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -2359,7 +2343,7 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 #endif // render a scanline - (this->*fragmentShader) (); + interlace_scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -2453,7 +2437,6 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -2488,7 +2471,7 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -2519,7 +2502,7 @@ void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4 #endif // render a scanline - (this->*fragmentShader) (); + interlace_scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureDetailMap2.cpp b/source/Irrlicht/CTRTextureDetailMap2.cpp index 3e75c2d9..78896647 100644 --- a/source/Irrlicht/CTRTextureDetailMap2.cpp +++ b/source/Irrlicht/CTRTextureDetailMap2.cpp @@ -88,7 +88,7 @@ public: virtual bool canWireFrame () { return true; } protected: - virtual void scanline_bilinear (); + virtual void fragmentShader(); }; @@ -105,7 +105,7 @@ CTRTextureDetailMap2::CTRTextureDetailMap2(CBurningVideoDriver* driver) /*! */ -void CTRTextureDetailMap2::scanline_bilinear () +void CTRTextureDetailMap2::fragmentShader() { tVideoSample *dst; @@ -140,12 +140,11 @@ void CTRTextureDetailMap2::scanline_bilinear () xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; - if ( dx < 0 ) return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -200,9 +199,9 @@ void CTRTextureDetailMap2::scanline_bilinear () tFixPoint r2, g2, b2; - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { - if ( (0 == EdgeTestPass) & i ) break; + if ( (0 == EdgeTestPass) & (i > line.x_edgetest)) break; #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -326,7 +325,7 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con #endif // rasterize upper sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[1] ) + if (F32_GREATER_0(scan.invDeltaY[1]) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; @@ -394,9 +393,10 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con #endif #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -427,7 +427,8 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); + if (EdgeTestPass & edge_test_first_line) break; scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -461,10 +462,10 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con } // rasterize lower sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[2] ) + if (F32_GREATER_0(scan.invDeltaY[2]) ) { // advance to middle point - if( (f32) 0.0 != scan.invDeltaY[1] ) + if(F32_GREATER_0(scan.invDeltaY[1]) ) { temp[0] = b->Pos.y - a->Pos.y; // dy @@ -521,7 +522,6 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -555,8 +555,10 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); + // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -587,7 +589,8 @@ void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, con #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); + if (EdgeTestPass & edge_test_first_line) break; scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureGouraud2.cpp b/source/Irrlicht/CTRTextureGouraud2.cpp index ef864606..1cd7bd18 100644 --- a/source/Irrlicht/CTRTextureGouraud2.cpp +++ b/source/Irrlicht/CTRTextureGouraud2.cpp @@ -167,7 +167,7 @@ void CTRTextureGouraud2::fragmentShader () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -254,10 +254,10 @@ void CTRTextureGouraud2::fragmentShader () u32 dIndex = ( line.y & 3 ) << 2; #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { //if test active only first pixel - if ( (0 == EdgeTestPass) & i ) break; + if ((0 == EdgeTestPass) & (i > line.x_edgetest)) break; #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -382,9 +382,9 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -551,9 +551,10 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const #endif #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -599,7 +600,7 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const #endif // render a scanline - fragmentShader (); + interlace_scanline fragmentShader (); if ( EdgeTestPass & edge_test_first_line ) break; @@ -734,7 +735,6 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -761,7 +761,7 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const scan.c[1][1] += scan.slopeC[1][1] * subPixel; #endif -#ifdef IPOL_C1 +#ifdef IPOL_C2 scan.c[2][0] += scan.slopeC[2][0] * subPixel; scan.c[2][1] += scan.slopeC[2][1] * subPixel; #endif @@ -782,9 +782,10 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const #endif #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -830,7 +831,7 @@ void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const #endif // render a scanline - fragmentShader (); + interlace_scanline fragmentShader (); if ( EdgeTestPass & edge_test_first_line ) break; diff --git a/source/Irrlicht/CTRTextureGouraudAdd2.cpp b/source/Irrlicht/CTRTextureGouraudAdd2.cpp index 040c83de..340cef59 100644 --- a/source/Irrlicht/CTRTextureGouraudAdd2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAdd2.cpp @@ -88,7 +88,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; //! constructor @@ -104,7 +104,7 @@ CTRTextureGouraudAdd2::CTRTextureGouraudAdd2(CBurningVideoDriver* driver) /*! */ -void CTRTextureGouraudAdd2::scanline_bilinear () +void CTRTextureGouraudAdd2::fragmentShader() { tVideoSample *dst; @@ -144,7 +144,7 @@ void CTRTextureGouraudAdd2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -203,7 +203,7 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -280,9 +280,9 @@ void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, co const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); // find if the major edge is left or right aligned f32 temp[4]; @@ -403,7 +403,7 @@ void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -434,7 +434,7 @@ void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -563,7 +563,7 @@ void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -594,7 +594,7 @@ void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp index 4a619530..0a880deb 100644 --- a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp @@ -143,7 +143,7 @@ void CTRTextureGouraudAddNoZ2::fragmentShader() return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -200,7 +200,7 @@ void CTRTextureGouraudAddNoZ2::fragmentShader() tFixPoint r2, g2, b2; #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -275,9 +275,9 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -401,7 +401,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -432,7 +432,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - fragmentShader(); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -526,7 +526,6 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -561,7 +560,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -592,7 +591,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - fragmentShader( ); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureGouraudAlpha.cpp b/source/Irrlicht/CTRTextureGouraudAlpha.cpp index 6e922359..995251bf 100644 --- a/source/Irrlicht/CTRTextureGouraudAlpha.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlpha.cpp @@ -88,7 +88,7 @@ public: virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; private: - void scanline_bilinear (); + void fragmentShader(); }; @@ -115,7 +115,7 @@ void CTRTextureGouraudAlpha2::OnSetMaterial(const SBurningShaderMaterial& materi /*! */ -void CTRTextureGouraudAlpha2::scanline_bilinear () +void CTRTextureGouraudAlpha2::fragmentShader() { tVideoSample *dst; @@ -155,7 +155,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -213,7 +213,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #endif #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -337,9 +337,9 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -463,7 +463,7 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -494,7 +494,7 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear ( ); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -588,7 +588,6 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -623,7 +622,7 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -654,7 +653,7 @@ void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear ( ); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp index 6a550334..2d7b9165 100644 --- a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp @@ -93,20 +93,6 @@ public: virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; -#if defined(PATCH_SUPERTUX_8_0_1) - SBurningShaderMaterial Material; - - virtual void setMaterial(const SBurningShaderMaterial &material) - { - Material = material; - } - - virtual void setParam(u32 index, f32 value) - { - OnSetMaterial(Material); -} -#endif - private: // fragment shader @@ -198,7 +184,7 @@ void CTRTextureGouraudAlphaNoZ::fragment_linear() return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -268,7 +254,7 @@ void CTRTextureGouraudAlphaNoZ::fragment_linear() tFixPoint a3,r3, g3, b3; #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -276,7 +262,7 @@ void CTRTextureGouraudAlphaNoZ::fragment_linear() #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif - + scissor_test_x { #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff @@ -418,7 +404,7 @@ void CTRTextureGouraudAlphaNoZ::fragment_linear_test() return; // slopes - const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + const f32 invDeltaX = fill_step_x(line.x[1] - line.x[0]); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -488,91 +474,91 @@ void CTRTextureGouraudAlphaNoZ::fragment_linear_test() tFixPoint a3, r3, g3, b3; #endif - for (s32 i = 0; i <= dx; ++i) + for (s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if (line.z[0] < z[i]) #endif #ifdef CMP_W - if (line.w[0] >= z[i]) + if (line.w[0] >= z[i]) #endif - - { + scissor_test_x + { #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff - const tFixPointu d = dithermask[dIndex | (i) & 3]; + const tFixPointu d = dithermask[dIndex | (i) & 3]; #ifdef INVERSE_W - inversew = fix_inverse32(line.w[0]); + inversew = fix_inverse32(line.w[0]); #endif - u32 argb = getTexel_plain(&IT[0], d + tofix(line.t[0][0].x, inversew), - d + tofix(line.t[0][0].y, inversew) - ); + u32 argb = getTexel_plain(&IT[0], d + tofix(line.t[0][0].x, inversew), + d + tofix(line.t[0][0].y, inversew) + ); - const tFixPoint alpha = (argb >> 24); - if (alpha > AlphaRef) - { + const tFixPoint alpha = (argb >> 24); + if (alpha > AlphaRef) + { #ifdef WRITE_Z - z[i] = line.z[0]; + z[i] = line.z[0]; #endif #ifdef WRITE_W - z[i] = line.w[0]; + z[i] = line.w[0]; #endif - dst[i] = PixelBlend32(dst[i], argb, alpha); - } + dst[i] = PixelBlend32(dst[i], argb, alpha); + } #else #ifdef INVERSE_W - inversew = fix_inverse32(line.w[0]); + inversew = fix_inverse32(line.w[0]); #endif - getSample_texture(a0, r0, g0, b0, - &IT[0], - tofix(line.t[0][0].x, inversew), - tofix(line.t[0][0].y, inversew) - ); + getSample_texture(a0, r0, g0, b0, + &IT[0], + tofix(line.t[0][0].x, inversew), + tofix(line.t[0][0].y, inversew) + ); - if (a0 > AlphaRef) - { + if (a0 > AlphaRef) + { #ifdef WRITE_Z - z[i] = line.z[0]; + z[i] = line.z[0]; #endif #ifdef WRITE_W - z[i] = line.w[0]; + z[i] = line.w[0]; #endif #ifdef IPOL_C0 - vec4_to_fix(a2, r2, g2, b2, line.c[0][0], inversew); + vec4_to_fix(a2, r2, g2, b2, line.c[0][0], inversew); - a0 = imulFix(a0, a2); //2D uses vertexalpha*texelalpha - r0 = imulFix(r0, r2); - g0 = imulFix(g0, g2); - b0 = imulFix(b0, b2); + a0 = imulFix(a0, a2); //2D uses vertexalpha*texelalpha + r0 = imulFix(r0, r2); + g0 = imulFix(g0, g2); + b0 = imulFix(b0, b2); - color_to_fix(r1, g1, b1, dst[i]); + color_to_fix(r1, g1, b1, dst[i]); - fix_color_norm(a0); + fix_color_norm(a0); - r2 = r1 + imulFix(a0, r0 - r1); - g2 = g1 + imulFix(a0, g0 - g1); - b2 = b1 + imulFix(a0, b0 - b1); - dst[i] = fix4_to_sample(a0, r2, g2, b2); + r2 = r1 + imulFix(a0, r0 - r1); + g2 = g1 + imulFix(a0, g0 - g1); + b2 = b1 + imulFix(a0, b0 - b1); + dst[i] = fix4_to_sample(a0, r2, g2, b2); #else - dst[i] = PixelBlend32(dst[i], - fix_to_sample(r0, g0, b0), - fixPointu_to_u32(a0) - ); -#endif - - } + dst[i] = PixelBlend32(dst[i], + fix_to_sample(r0, g0, b0), + fixPointu_to_u32(a0) + ); #endif } +#endif + + } #ifdef IPOL_Z line.z[0] += slopeZ; @@ -639,7 +625,7 @@ void CTRTextureGouraudAlphaNoZ::fragment_point_noz() return; // slopes - const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + const f32 invDeltaX = fill_step_x(line.x[1] - line.x[0]); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -708,15 +694,15 @@ void CTRTextureGouraudAlphaNoZ::fragment_point_noz() #ifdef IPOL_C1 tFixPoint a3, r3, g3, b3; #endif - for (s32 i = 0; i <= dx; ++i) + for (s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z - if (line.z[0] < z[i]) + //if (line.z[0] < z[i]) #endif #ifdef CMP_W // if (line.w[0] >= z[i]) #endif - + scissor_test_x { #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff @@ -827,9 +813,9 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -968,7 +954,7 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -1004,6 +990,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a #endif // render a scanline + interlace_scanline + scissor_test_y (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; @@ -1112,7 +1100,6 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL - subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center @@ -1152,7 +1139,7 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -1188,6 +1175,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a #endif // render a scanline + interlace_scanline + scissor_test_y (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; diff --git a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp index c2b4625d..b287e47b 100644 --- a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp @@ -89,11 +89,16 @@ public: //! draws an indexed triangle list virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; - + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; private: - void scanline_bilinear (); + // fragment shader + typedef void (CTRTextureGouraudNoZ2::* tFragmentShader) (); + void fragment_bilinear(); + void fragment_no_filter(); + + tFragmentShader fragmentShader; }; //! constructor @@ -103,13 +108,32 @@ CTRTextureGouraudNoZ2::CTRTextureGouraudNoZ2(CBurningVideoDriver* driver) #ifdef _DEBUG setDebugName("CTRTextureGouraudNoZ2"); #endif + + fragmentShader = &CTRTextureGouraudNoZ2::fragment_bilinear; } - - /*! */ -void CTRTextureGouraudNoZ2::scanline_bilinear ( ) +void CTRTextureGouraudNoZ2::OnSetMaterial(const SBurningShaderMaterial& material) +{ + + if (material.org.TextureLayer[0].BilinearFilter || + material.org.TextureLayer[0].TrilinearFilter || + material.org.TextureLayer[0].AnisotropicFilter + ) + { + fragmentShader = &CTRTextureGouraudNoZ2::fragment_bilinear; + } + else + { + fragmentShader = &CTRTextureGouraudNoZ2::fragment_no_filter; + } + +} + +/*! +*/ +void CTRTextureGouraudNoZ2::fragment_bilinear() { tVideoSample *dst; @@ -149,7 +173,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -168,7 +192,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif #ifdef SUBTEXEL - subPixel = ( (f32) xStart ) - line.x[0]; + subPixel = ((f32) xStart) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif @@ -200,7 +224,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) tFixPoint ty0; tFixPoint r0, g0, b0; - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -208,7 +232,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif - + scissor_test_x { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); @@ -248,6 +272,146 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) } +/*! +*/ +void CTRTextureGouraudNoZ2::fragment_no_filter() +{ + tVideoSample* dst; + +#ifdef USE_ZBUFFER + fp24* z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); + + dx = xEnd - xStart; + if (dx < 0) + return; + + // slopes + const f32 invDeltaX = fill_step_x(line.x[1] - line.x[0]); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC = (line.c[1] - line.c[0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ((f32)xStart) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0] += slopeC * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + (line.y * RenderTarget->getDimension().Width) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*)DepthBuffer->lock() + (line.y * RenderTarget->getDimension().Width) + xStart; +#endif + + + f32 inversew = FIX_POINT_F32_MUL; + + tFixPoint tx0; + tFixPoint ty0; + //tFixPoint r0, g0, b0; + + for (s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) + { +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + //scissor_test_x + { + #ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); + #endif + tx0 = tofix(line.t[0][0].x,inversew); + ty0 = tofix(line.t[0][0].y,inversew); + //skybox + dst[i] = getTexel_plain(&IT[0], tx0, ty0); + + //getSample_texture ( r0, g0, b0, IT+0, tx0, ty0 ); + //dst[i] = fix_to_sample( r0, g0, b0 ); + + #ifdef WRITE_Z + z[i] = line.z[0]; + #endif + #ifdef WRITE_W + z[i] = line.w[0]; + #endif + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0] += slopeC; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + +} + void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y @@ -258,10 +422,11 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; + // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -315,7 +480,7 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // rasterize upper sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[1] ) + if (F32_GREATER_0(scan.invDeltaY[1]) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; @@ -385,7 +550,7 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -415,8 +580,11 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co line.t[1][scan.right] = scan.t[1][1]; #endif + // render a scanline - scanline_bilinear ( ); + interlace_scanline + scissor_test_y + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -450,10 +618,10 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co } // rasterize lower sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[2] ) + if (F32_GREATER_0(scan.invDeltaY[2]) ) { // advance to middle point - if( (f32) 0.0 != scan.invDeltaY[1] ) + if(F32_GREATER_0(scan.invDeltaY[1]) ) { temp[0] = b->Pos.y - a->Pos.y; // dy @@ -545,7 +713,7 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -576,7 +744,9 @@ void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, co #endif // render a scanline - scanline_bilinear (); + interlace_scanline + scissor_test_y + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp index 4b9c4c20..b9ff381e 100644 --- a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp +++ b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp @@ -93,7 +93,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; @@ -110,7 +110,7 @@ CTRTextureVertexAlpha2::CTRTextureVertexAlpha2(CBurningVideoDriver* driver) /*! */ -void CTRTextureVertexAlpha2::scanline_bilinear ( ) +void CTRTextureVertexAlpha2::fragmentShader( ) { tVideoSample *dst; @@ -150,7 +150,7 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -219,7 +219,7 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #endif - for ( s32 i = 0; i <= dx; ++i ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -332,9 +332,9 @@ void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, c const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -473,7 +473,7 @@ void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -509,7 +509,7 @@ void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -656,7 +656,7 @@ void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -692,7 +692,7 @@ void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureLightMap2_Add.cpp b/source/Irrlicht/CTRTextureLightMap2_Add.cpp index 11d430bf..61497d3b 100644 --- a/source/Irrlicht/CTRTextureLightMap2_Add.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_Add.cpp @@ -86,7 +86,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; @@ -103,7 +103,7 @@ CTRTextureLightMap2_Add::CTRTextureLightMap2_Add(CBurningVideoDriver* driver) /*! */ -REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () +REALINLINE void CTRTextureLightMap2_Add::fragmentShader() { tVideoSample *dst; @@ -143,7 +143,7 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -199,7 +199,7 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif - for ( s32 i = 0; i <= dx; i++ ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -274,9 +274,9 @@ void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -400,7 +400,7 @@ void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -431,7 +431,7 @@ void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -560,7 +560,7 @@ void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -591,7 +591,7 @@ void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureLightMap2_M1.cpp b/source/Irrlicht/CTRTextureLightMap2_M1.cpp index 1295d3c7..b8d0893f 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M1.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M1.cpp @@ -121,7 +121,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -193,7 +193,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () #endif - for ( ;i <= dx; i++ ) + for ( ;i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) @@ -255,9 +255,9 @@ void CTRTextureLightMap2_M1::drawTriangle(const s4DVertex* burning_restrict a, c const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -381,7 +381,7 @@ void CTRTextureLightMap2_M1::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -542,7 +542,7 @@ void CTRTextureLightMap2_M1::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; diff --git a/source/Irrlicht/CTRTextureLightMap2_M2.cpp b/source/Irrlicht/CTRTextureLightMap2_M2.cpp index 5976cfb8..19d051f3 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M2.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M2.cpp @@ -121,7 +121,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -254,9 +254,9 @@ void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, c const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -380,7 +380,7 @@ void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -411,7 +411,7 @@ void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear2 (); + interlace_scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -541,7 +541,7 @@ void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -572,7 +572,7 @@ void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear2 (); + interlace_scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureLightMap2_M4.cpp b/source/Irrlicht/CTRTextureLightMap2_M4.cpp index b33a0e0c..a78b1e3e 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M4.cpp @@ -93,10 +93,10 @@ private: void scanline_bilinear2_mag (); void scanline_bilinear2_min (); #else - #define scanline_bilinear2_mag scanline_bilinear + #define scanline_bilinear2_mag fragmentShader #endif - void scanline_bilinear (); + void fragmentShader(); }; @@ -130,7 +130,7 @@ void CTRTextureLightMap2_M4::scanline_bilinear2_mag () SOFTWARE_DRIVER_2_CLIPCHECK; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel i = ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -202,7 +202,7 @@ void CTRTextureLightMap2_M4::scanline_bilinear2_mag () #endif - for ( ;i <= dx; i++ ) + for ( ;i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) @@ -271,7 +271,7 @@ void CTRTextureLightMap2_M4::scanline_bilinear2_min () SOFTWARE_DRIVER_2_CLIPCHECK; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -334,7 +334,7 @@ void CTRTextureLightMap2_M4::scanline_bilinear2_min () tFixPoint r1, g1, b1; - for ( ;i <= dx; i++ ) + for ( ;i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) @@ -393,9 +393,9 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restric const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -519,7 +519,7 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restric #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -550,7 +550,7 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restric #endif // render a scanline - scanline_bilinear2_min (); + interlace_scanline scanline_bilinear2_min (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -680,7 +680,7 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restric #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -711,7 +711,7 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restric #endif // render a scanline - scanline_bilinear2_min (); + interlace_scanline scanline_bilinear2_min (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -769,9 +769,9 @@ void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, c return; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); //if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) // return; @@ -896,7 +896,7 @@ void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -927,7 +927,7 @@ void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear2_mag (); + interlace_scanline scanline_bilinear2_mag (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -1057,7 +1057,7 @@ void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, c #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -1088,7 +1088,7 @@ void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, c #endif // render a scanline - scanline_bilinear2_mag (); + interlace_scanline scanline_bilinear2_mag (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp index 55e7ffc0..08f5285d 100644 --- a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp @@ -86,7 +86,7 @@ public: private: - void scanline_bilinear (); + void fragmentShader(); }; @@ -103,7 +103,7 @@ CTRGTextureLightMap2_M4::CTRGTextureLightMap2_M4(CBurningVideoDriver* driver) /*! */ -void CTRGTextureLightMap2_M4::scanline_bilinear () +void CTRGTextureLightMap2_M4::fragmentShader() { tVideoSample *dst; @@ -143,7 +143,7 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -201,7 +201,7 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () tFixPoint r3, g3, b3; #endif - for ( s32 i = 0; i <= dx; i++ ) + for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) @@ -283,9 +283,9 @@ void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_0 ( scan.invDeltaY[0] ) ) return; @@ -411,7 +411,7 @@ void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -442,7 +442,7 @@ void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -573,7 +573,7 @@ void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -604,7 +604,7 @@ void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, #endif // render a scanline - scanline_bilinear (); + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; diff --git a/source/Irrlicht/CTRTextureWire2.cpp b/source/Irrlicht/CTRTextureWire2.cpp index 61a42274..af81c4a4 100644 --- a/source/Irrlicht/CTRTextureWire2.cpp +++ b/source/Irrlicht/CTRTextureWire2.cpp @@ -91,7 +91,7 @@ public: virtual bool canPointCloud() _IRR_OVERRIDE_ { return true; } protected: - virtual void scanline_bilinear (); + virtual void fragmentShader(); void renderAlphaLine ( const s4DVertex *a,const s4DVertex *b ) const; void renderLine ( const s4DVertex *a,const s4DVertex *b, int renderZero = 0 ) const; @@ -114,7 +114,7 @@ CTRTextureWire2::CTRTextureWire2(CBurningVideoDriver* driver) */ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int renderZero) const { - int pitch0 = RenderTarget->getDimension().Width << VIDEO_SAMPLE_GRANULARITY; + int pitch0 = RenderTarget->getDimension().Width << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY; #ifdef USE_ZBUFFER int pitch1 = RenderTarget->getDimension().Width << 2; #endif @@ -138,7 +138,7 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int re fp24 *z; #endif - int xInc0 = 1 << VIDEO_SAMPLE_GRANULARITY; + int xInc0 = 1 << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY; int yInc0 = pitch0; #ifdef USE_ZBUFFER @@ -148,7 +148,7 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int re if ( dx < 0 ) { - xInc0 = - ( 1 << VIDEO_SAMPLE_GRANULARITY); + xInc0 = - ( 1 << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY); #ifdef USE_ZBUFFER xInc1 = -4; #endif @@ -173,7 +173,7 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int re } SOFTWARE_DRIVER_2_CLIPCHECK_WIRE; - dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( aposy * pitch0 ) + (aposx* (1<< VIDEO_SAMPLE_GRANULARITY) ) ); + dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( aposy * pitch0 ) + (aposx* (1<< SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY) ) ); #ifdef USE_ZBUFFER z = (fp24*) ( (u8*) (fp24*) DepthBuffer->lock() + ( aposy * pitch1 ) + (aposx << 2 ) ); #endif @@ -182,7 +182,7 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int re m = dy << 1; // slopes - const f32 invDeltaX = reciprocal_zero2( (f32)dx ); + const f32 invDeltaX = fill_step_x( (f32)dx ); #ifdef IPOL_Z f32 slopeZ = (b->Pos.z - a->Pos.z) * invDeltaX; @@ -283,7 +283,7 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int re } -void CTRTextureWire2::scanline_bilinear() +void CTRTextureWire2::fragmentShader() { } diff --git a/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp b/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp index 8fb92140..eccb6787 100644 --- a/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp +++ b/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp @@ -149,7 +149,7 @@ void CTR_transparent_reflection_2_layer::fragmentShader() return; // slopes - const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -206,7 +206,7 @@ void CTR_transparent_reflection_2_layer::fragmentShader() switch(MaterialType) { default: case EMT_REFLECTION_2_LAYER: - for (s32 i = 0; i <= dx; ++i) + for (s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if (line.z[0] < z[i]) @@ -263,7 +263,7 @@ void CTR_transparent_reflection_2_layer::fragmentShader() break; case EMT_TRANSPARENT_REFLECTION_2_LAYER: - for (s32 i = 0; i <= dx; ++i) + for (s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X) { #ifdef CMP_Z if (line.z[0] < z[i]) @@ -344,9 +344,9 @@ void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = reciprocal_zero( ca ); - scan.invDeltaY[1] = reciprocal_zero( ba ); - scan.invDeltaY[2] = reciprocal_zero( cb ); + scan.invDeltaY[0] = fill_step_y( ca ); + scan.invDeltaY[1] = fill_step_y( ba ); + scan.invDeltaY[2] = fill_step_y( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -470,7 +470,7 @@ void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -501,6 +501,7 @@ void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning #endif // render a scanline + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; @@ -630,7 +631,7 @@ void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning #endif // rasterize the edge scanlines - for( line.y = yStart; line.y <= yEnd; ++line.y) + for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -661,6 +662,7 @@ void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning #endif // render a scanline + interlace_scanline fragmentShader(); scan.x[0] += scan.slopeX[0]; diff --git a/source/Irrlicht/IBurningShader.cpp b/source/Irrlicht/IBurningShader.cpp index a375ef38..c7945e8c 100644 --- a/source/Irrlicht/IBurningShader.cpp +++ b/source/Irrlicht/IBurningShader.cpp @@ -12,29 +12,37 @@ namespace irr { - - namespace video { - const tFixPointu IBurningShader::dithermask[] = - { - 0x00,0x80,0x20,0xa0, - 0xc0,0x40,0xe0,0x60, - 0x30,0xb0,0x10,0x90, - 0xf0,0x70,0xd0,0x50 - }; +const tFixPointu IBurningShader::dithermask[] = +{ + 0x00,0x80,0x20,0xa0, + 0xc0,0x40,0xe0,0x60, + 0x30,0xb0,0x10,0x90, + 0xf0,0x70,0xd0,0x50 +}; void IBurningShader::constructor_IBurningShader(CBurningVideoDriver* driver) { - #ifdef _DEBUG +#ifdef _DEBUG setDebugName("IBurningShader"); - #endif +#endif + + if (((unsigned long long)&scan & 15) || ((unsigned long long)&line & 15)) + { + os::Printer::log("BurningVideo Shader not 16 byte aligned", ELL_ERROR); + _IRR_DEBUG_BREAK_IF(1); + } + + Interlaced.enable = 0; + Interlaced.bypass = 1; + Interlaced.nr = 0; EdgeTestPass = edge_test_pass; EdgeTestPass_stack = edge_test_pass; - for ( u32 i = 0; i < BURNING_MATERIAL_MAX_TEXTURES; ++i ) + for (u32 i = 0; i < BURNING_MATERIAL_MAX_TEXTURES; ++i) { IT[i].Texture = 0; } @@ -44,12 +52,12 @@ void IBurningShader::constructor_IBurningShader(CBurningVideoDriver* driver) RenderTarget = 0; ColorMask = COLOR_BRIGHT_WHITE; - DepthBuffer = (CDepthBuffer*) driver->getDepthBuffer (); - if ( DepthBuffer ) + DepthBuffer = (CDepthBuffer*)driver->getDepthBuffer(); + if (DepthBuffer) DepthBuffer->grab(); - Stencil = (CStencilBuffer*) driver->getStencilBuffer (); - if ( Stencil ) + Stencil = (CStencilBuffer*)driver->getStencilBuffer(); + if (Stencil) Stencil->grab(); stencilOp[0] = StencilOp_KEEP; @@ -76,7 +84,7 @@ IBurningShader::IBurningShader( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, - const c8* geometryShaderProgram , + const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, @@ -109,9 +117,9 @@ IBurningShader::~IBurningShader() if (Stencil) Stencil->drop(); - for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) + for (u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i) { - if ( IT[i].Texture ) + if (IT[i].Texture) IT[i].Texture->drop(); } @@ -121,12 +129,14 @@ IBurningShader::~IBurningShader() } //! sets a render target -void IBurningShader::setRenderTarget(video::IImage* surface, const core::rect& viewPort) +void IBurningShader::setRenderTarget(video::IImage* surface, const core::rect& viewPort, const interlaced_control interlaced) { + Interlaced = interlaced; + if (RenderTarget) RenderTarget->drop(); - RenderTarget = (video::CImage* ) surface; + RenderTarget = (video::CImage*) surface; if (RenderTarget) { @@ -138,16 +148,16 @@ void IBurningShader::setRenderTarget(video::IImage* surface, const core::rectTexture) + if (it->Texture) it->Texture->drop(); it->Texture = texture; - if ( it->Texture) + if (it->Texture) { it->Texture->grab(); @@ -156,48 +166,52 @@ void IBurningShader::setTextureParam( const size_t stage, video::CSoftwareTextur //only mipmap chain (means positive lodFactor) u32 existing_level = it->Texture->getMipmapLevel(lodFactor); - it->data = (tVideoSample*) it->Texture->lock(ETLM_READ_ONLY, existing_level, 0); +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + it->data = (tVideoSample*)it->Texture->lock(ETLM_READ_ONLY, existing_level, 0); +#else + it->data = (tVideoSample*)it->Texture->lock(ETLM_READ_ONLY, existing_level); +#endif // prepare for optimal fixpoint - it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); + it->pitchlog2 = s32_log2_s32(it->Texture->getPitch()); - const core::dimension2d &dim = it->Texture->getSize(); - it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; - it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; + const core::dimension2d& dim = it->Texture->getSize(); + it->textureXMask = s32_to_fixPoint(dim.Width - 1) & FIX_POINT_UNSIGNED_MASK; + it->textureYMask = s32_to_fixPoint(dim.Height - 1) & FIX_POINT_UNSIGNED_MASK; } } //emulate a line with degenerate triangle and special shader mode (not perfect...) -void IBurningShader::drawLine ( const s4DVertex *a,const s4DVertex *b) +void IBurningShader::drawLine(const s4DVertex* a, const s4DVertex* b) { sVec2 d; d.x = b->Pos.x - a->Pos.x; d.x *= d.x; d.y = b->Pos.y - a->Pos.y; d.y *= d.y; //if ( d.x * d.y < 0.001f ) return; - if ( a->Pos.x > b->Pos.x ) swapVertexPointer(&a, &b); + if (a->Pos.x > b->Pos.x) swapVertexPointer(&a, &b); s4DVertex c = *a; - const f32 w = (f32)RenderTarget->getDimension().Width-1; - const f32 h = (f32)RenderTarget->getDimension().Height-1; + const f32 w = (f32)RenderTarget->getDimension().Width - 1; + const f32 h = (f32)RenderTarget->getDimension().Height - 1; - if ( d.x < 2.f ) { c.Pos.x = b->Pos.x + 1.f + d.y; if ( c.Pos.x > w ) c.Pos.x = w; } + if (d.x < 2.f) { c.Pos.x = b->Pos.x + 1.f + d.y; if (c.Pos.x > w) c.Pos.x = w; } else c.Pos.x = b->Pos.x; - if ( d.y < 2.f ) { c.Pos.y = b->Pos.y + 1.f; if ( c.Pos.y > h ) c.Pos.y = h; EdgeTestPass |= edge_test_first_line; } + if (d.y < 2.f) { c.Pos.y = b->Pos.y + 1.f; if (c.Pos.y > h) c.Pos.y = h; EdgeTestPass |= edge_test_first_line; } - drawTriangle ( a,b,&c ); + drawTriangle(a, b, &c); EdgeTestPass &= ~edge_test_first_line; } -void IBurningShader::drawPoint(const s4DVertex *a) +void IBurningShader::drawPoint(const s4DVertex* a) { } -void IBurningShader::drawWireFrameTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void IBurningShader::drawWireFrameTriangle(const s4DVertex* a, const s4DVertex* b, const s4DVertex* c) { - if ( EdgeTestPass & edge_test_pass ) drawTriangle(a, b, c); + if (EdgeTestPass & edge_test_pass) drawTriangle(a, b, c); else if (EdgeTestPass & edge_test_point) { drawPoint(a); @@ -256,7 +270,7 @@ void IBurningShader::setBasicRenderStates(const SMaterial& material, const SMate Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } -s32 IBurningShader::getShaderConstantID(EBurningUniformFlags flags,const c8* name) +s32 IBurningShader::getShaderConstantID(EBurningUniformFlags flags, const c8* name) { if (!name || !name[0]) return -1; @@ -285,7 +299,7 @@ const char* tiny_itoa(s32 value, int base) b[p] = '\0'; do { - b[--p] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[value%base]; + b[--p] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[value % base]; value /= base; } while (value && p > 0); @@ -302,7 +316,7 @@ bool IBurningShader::setShaderConstantID(EBurningUniformFlags flags, s32 index, BurningUniform add; while ((u32)index >= UniformInfo.size()) { - tiny_strcpy(add.name, tiny_itoa(UniformInfo.size(),10)); + tiny_strcpy(add.name, tiny_itoa(UniformInfo.size(), 10)); add.type = flags; UniformInfo.push_back(add); } @@ -340,7 +354,7 @@ void IBurningShader::setVertexShaderConstant(const f32* data, s32 startRegister, c8 name[BL_ACTIVE_UNIFORM_MAX_LENGTH]; tiny_strcpy(name, tiny_itoa(startRegister, 10)); - setShaderConstantID(BL_VERTEX_FLOAT, getShaderConstantID(BL_VERTEX_PROGRAM,name), data, constantAmount); + setShaderConstantID(BL_VERTEX_FLOAT, getShaderConstantID(BL_VERTEX_PROGRAM, name), data, constantAmount); } void IBurningShader::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) diff --git a/source/Irrlicht/IBurningShader.h b/source/Irrlicht/IBurningShader.h index 8a9a8180..748a9a40 100644 --- a/source/Irrlicht/IBurningShader.h +++ b/source/Irrlicht/IBurningShader.h @@ -215,7 +215,6 @@ namespace video }; - class CBurningVideoDriver; class IBurningShader : public IMaterialRenderer, public IMaterialRendererServices { @@ -247,7 +246,7 @@ namespace video virtual ~IBurningShader(); //! sets a render target - virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort); + virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort, const interlaced_control interlaced); //! sets the Texture virtual void setTextureParam( const size_t stage, video::CSoftwareTexture2* texture, s32 lodFactor); @@ -299,14 +298,38 @@ namespace video virtual bool setPixelShaderConstant(s32 index, const u32* ints, int count) _IRR_OVERRIDE_; virtual IVideoDriver* getVideoDriver() _IRR_OVERRIDE_; +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), floats, count); + } + virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), (const s32*)bools, count); + } + virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), ints, count); + } + + virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), floats, count); + } + virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), (const s32*)bools, count); + } + virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), ints, count); + } +#endif + //used if no color interpolation is defined void setPrimitiveColor(const video::SColor& color) { - #if BURNINGSHADER_COLOR_FORMAT == ECF_A8R8G8B8 - PrimitiveColor = color.color; - #else - PrimitiveColor = color.toA1R5G5B5(); - #endif + PrimitiveColor = color_to_sample(color); } void setTLFlag(size_t in /*eTransformLightFlags*/) { @@ -314,11 +337,7 @@ namespace video } void setFog(SColor color_fog) { -#if BURNINGSHADER_COLOR_FORMAT == ECF_A8R8G8B8 - fog_color_sample = color_fog.color; -#else - fog_color_sample = color_fog.toA1R5G5B5(); -#endif + fog_color_sample = color_to_sample(color_fog); color_to_fix(fog_color, fog_color_sample); } void setScissor(const AbsRectangle& scissor) @@ -349,14 +368,15 @@ namespace video static const tFixPointu dithermask[ 4 * 4]; //draw degenerate triangle as line (left edge) drawTriangle -> holes,drawLine dda/bresenham - int EdgeTestPass; //edge_test_flag - int EdgeTestPass_stack; + size_t EdgeTestPass; //edge_test_flag + size_t EdgeTestPass_stack; + interlaced_control Interlaced; // passed from driver eBurningStencilOp stencilOp[4]; tFixPoint AlphaRef; int RenderPass_ShaderIsTransparent; - sScanConvertData scan; + sScanConvertData ALIGN(16) scan; sScanLineData line; tVideoSample PrimitiveColor; //used if no color interpolation is defined @@ -365,6 +385,17 @@ namespace video tVideoSample fog_color_sample; AbsRectangle Scissor; + + inline tVideoSample color_to_sample(const video::SColor& color) const + { + //RenderTarget->getColorFormat() +#if SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT == ECF_A8R8G8B8 + return color.color; +#else + return color.toA1R5G5B5(); +#endif + } + }; diff --git a/source/Irrlicht/IDepthBuffer.h b/source/Irrlicht/IDepthBuffer.h index 89f604f3..996926c8 100644 --- a/source/Irrlicht/IDepthBuffer.h +++ b/source/Irrlicht/IDepthBuffer.h @@ -21,7 +21,7 @@ namespace video virtual ~IDepthBuffer() {}; //! clears the zbuffer - virtual void clear(f32 value) = 0; + virtual void clear(f32 value, const interlaced_control interlaced) = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; @@ -52,7 +52,7 @@ namespace video virtual ~IStencilBuffer() {}; //! clears the stencil buffer - virtual void clear(u8 value) = 0; + virtual void clear(u32 value, const interlaced_control interlaced) = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; diff --git a/source/Irrlicht/S4DVertex.h b/source/Irrlicht/S4DVertex.h index 92abbb26..667fd6d4 100644 --- a/source/Irrlicht/S4DVertex.h +++ b/source/Irrlicht/S4DVertex.h @@ -79,6 +79,13 @@ struct sVec2 #include "irrpack.h" +//! sVec2Pack is Irrlicht S3DVertex,S3DVertex2TCoords,S3DVertexTangents Texutre Coordinates. +// Start address is not 4 byte aligned +struct sVec2Pack +{ + f32 x, y; +}; + //! sVec3Pack used in BurningShader, packed direction struct sVec3Pack { @@ -529,7 +536,7 @@ typedef s4DVertex s4DVertexPair; struct SAligned4DVertex { SAligned4DVertex() - :data(0),mem(0), ElementSize(0) {} + :data(0),ElementSize(0),mem(0) {} virtual ~SAligned4DVertex () { @@ -553,8 +560,11 @@ struct SAligned4DVertex } s4DVertex* data; //align to 16 byte - u8* mem; size_t ElementSize; + +private: + + u8* mem; }; //#define memcpy_s4DVertexPair(dst,src) memcpy(dst,src,sizeof_s4DVertex * 2) @@ -732,7 +742,7 @@ struct sScanConvertData { u32 left; // major edge left/right u32 right; // !left - u32 _unused_pack[2]; + u8 _unused_pack[8]; f32 invDeltaY[4]; // inverse edge delta for screen space sorted triangle @@ -767,7 +777,7 @@ struct sScanConvertData struct sScanLineData { s32 y; // y position of scanline - u32 _unused_pack[1]; + u8 _unused_pack[4]; f32 x[2]; // x start, x end of scanline #if defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) || defined ( SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT ) @@ -776,7 +786,8 @@ struct sScanLineData f32 z[2]; // z start, z end of scanline #endif - u32 _unused_pack_1[2]; + s32 x_edgetest; // slope x + u8 _unused_pack_1[4]; #if BURNING_MATERIAL_MAX_COLORS > 0 sVec4 c[BURNING_MATERIAL_MAX_COLORS][2]; // color start, color end of scanline diff --git a/source/Irrlicht/SoftwareDriver2_compile_config.h b/source/Irrlicht/SoftwareDriver2_compile_config.h index 725ba1a9..897049ac 100644 --- a/source/Irrlicht/SoftwareDriver2_compile_config.h +++ b/source/Irrlicht/SoftwareDriver2_compile_config.h @@ -10,140 +10,167 @@ // Generic Render Flags for burning's video rasterizer // defined now in irrlicht compile config -#if defined(PATCH_SUPERTUX_8_0_1) - #undef BURNINGVIDEO_RENDERER_BEAUTIFUL +#if 1 && defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) +#undef BURNINGVIDEO_RENDERER_BEAUTIFUL + +#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#define SOFTWARE_DRIVER_2_SUBTEXEL +#define SOFTWARE_DRIVER_2_BILINEAR +#define SOFTWARE_DRIVER_2_LIGHTING +#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +//#define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR +#define SOFTWARE_DRIVER_2_USE_WBUFFER +#define SOFTWARE_DRIVER_2_32BIT +#define SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT ECF_A8R8G8B8 +#define SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT ECF_A8R8G8B8 +#define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 +#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM +#define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 +#define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN +#define SOFTWARE_DRIVER_2_CLIPPING +#define SOFTWARE_DRIVER_2_2D_AS_3D +#define SOFTWARE_DRIVER_2_INTERLACED - //#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #define SOFTWARE_DRIVER_2_SUBTEXEL - //#define SOFTWARE_DRIVER_2_BILINEAR - #define SOFTWARE_DRIVER_2_LIGHTING - #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR - #define SOFTWARE_DRIVER_2_32BIT - #define SOFTWARE_DRIVER_2_MIPMAPPING - #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 - #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN - #define SOFTWARE_DRIVER_2_CLIPPING - #define SOFTWARE_DRIVER_2_2D_AS_2D #endif - #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL - #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #define SOFTWARE_DRIVER_2_SUBTEXEL - #define SOFTWARE_DRIVER_2_BILINEAR - #define SOFTWARE_DRIVER_2_LIGHTING - #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR - #define SOFTWARE_DRIVER_2_32BIT - #define SOFTWARE_DRIVER_2_MIPMAPPING - #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 - #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN - #define SOFTWARE_DRIVER_2_CLIPPING - #define SOFTWARE_DRIVER_2_2D_AS_3D +#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#define SOFTWARE_DRIVER_2_SUBTEXEL +#define SOFTWARE_DRIVER_2_BILINEAR +#define SOFTWARE_DRIVER_2_LIGHTING +#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR +#define SOFTWARE_DRIVER_2_USE_WBUFFER +#define SOFTWARE_DRIVER_2_32BIT +#define SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT ECF_A8R8G8B8 +#define SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT ECF_A8R8G8B8 +#define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0x100000 +#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM +#define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 16 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 +#define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN +#define SOFTWARE_DRIVER_2_CLIPPING +#define SOFTWARE_DRIVER_2_2D_AS_3D +#define SOFTWARE_DRIVER_2_INTERLACED #endif //! Set Flags for Windows Mobile #ifdef BURNINGVIDEO_RENDERER_CE - #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #define SOFTWARE_DRIVER_2_SUBTEXEL - //#define SOFTWARE_DRIVER_2_BILINEAR - //#define SOFTWARE_DRIVER_2_LIGHTING - #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #define SOFTWARE_DRIVER_2_16BIT - #define SOFTWARE_DRIVER_2_MIPMAPPING - #define SOFTWARE_DRIVER_2_USE_WBUFFER - //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 64 - #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN - //#define SOFTWARE_DRIVER_2_CLIPPING - #define SOFTWARE_DRIVER_2_2D_AS_2D +#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#define SOFTWARE_DRIVER_2_SUBTEXEL +//#define SOFTWARE_DRIVER_2_BILINEAR +//#define SOFTWARE_DRIVER_2_LIGHTING +#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#define SOFTWARE_DRIVER_2_USE_WBUFFER +#define SOFTWARE_DRIVER_2_16BIT +#define SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT ECF_A1R5G5B5 +#define SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT ECF_A1R5G5B5 +#define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 64 +//#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM +#define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 +#define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN +//#define SOFTWARE_DRIVER_2_CLIPPING +#define SOFTWARE_DRIVER_2_2D_AS_2D #endif #ifdef BURNINGVIDEO_RENDERER_FAST - #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #define SOFTWARE_DRIVER_2_SUBTEXEL - //#define SOFTWARE_DRIVER_2_BILINEAR - //#define SOFTWARE_DRIVER_2_LIGHTING - #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - //#define SOFTWARE_DRIVER_2_32BIT - #define SOFTWARE_DRIVER_2_16BIT - #define SOFTWARE_DRIVER_2_MIPMAPPING - #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 - #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN - #define SOFTWARE_DRIVER_2_CLIPPING - #define SOFTWARE_DRIVER_2_2D_AS_2D +#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#define SOFTWARE_DRIVER_2_SUBTEXEL +//#define SOFTWARE_DRIVER_2_BILINEAR +//#define SOFTWARE_DRIVER_2_LIGHTING +#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#define SOFTWARE_DRIVER_2_USE_WBUFFER +#define SOFTWARE_DRIVER_2_16BIT +#define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 +#define SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT ECF_A1R5G5B5 +#define SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT ECF_A1R5G5B5 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 +#define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN +#define SOFTWARE_DRIVER_2_CLIPPING +#define SOFTWARE_DRIVER_2_2D_AS_2D +#define SOFTWARE_DRIVER_2_INTERLACED #endif #ifdef BURNINGVIDEO_RENDERER_ULTRA_FAST - #define BURNINGVIDEO_RENDERER_FAST +#define BURNINGVIDEO_RENDERER_FAST - //#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - //#define SOFTWARE_DRIVER_2_SUBTEXEL - //#define SOFTWARE_DRIVER_2_BILINEAR - //#define SOFTWARE_DRIVER_2_LIGHTING - #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - //#define SOFTWARE_DRIVER_2_32BIT - #define SOFTWARE_DRIVER_2_16BIT - //#define SOFTWARE_DRIVER_2_MIPMAPPING - //#define SOFTWARE_DRIVER_2_USE_WBUFFER - //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 - #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN - //#define SOFTWARE_DRIVER_2_CLIPPING - #define SOFTWARE_DRIVER_2_2D_AS_2D +//#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +//#define SOFTWARE_DRIVER_2_SUBTEXEL +//#define SOFTWARE_DRIVER_2_BILINEAR +//#define SOFTWARE_DRIVER_2_LIGHTING +#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +//#define SOFTWARE_DRIVER_2_USE_WBUFFER +#define SOFTWARE_DRIVER_2_16BIT +#define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 +#define SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT ECF_A1R5G5B5 +#define SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT ECF_A1R5G5B5 +//#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM +#define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 1 +#define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 +#define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN +//#define SOFTWARE_DRIVER_2_CLIPPING +#define SOFTWARE_DRIVER_2_2D_AS_2D +#define SOFTWARE_DRIVER_2_INTERLACED #endif -// Derivate flags - -// texture format -#ifdef SOFTWARE_DRIVER_2_32BIT - #define BURNINGSHADER_COLOR_FORMAT ECF_A8R8G8B8 -#else - #define BURNINGSHADER_COLOR_FORMAT ECF_A1R5G5B5 -#endif - -// mip mapping - precalculated texture filter -#if defined ( SOFTWARE_DRIVER_2_MIPMAPPING ) - #if defined( BURNINGVIDEO_RENDERER_BEAUTIFUL ) - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 16 - #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 - #elif defined ( BURNINGVIDEO_RENDERER_CE ) - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 - #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 - #else - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 - #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 - #endif -#else - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 1 - #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 -#endif - - #ifndef REALINLINE - #ifdef _MSC_VER - #define REALINLINE __forceinline - #else - #define REALINLINE inline - #endif +#ifdef _MSC_VER +#define REALINLINE __forceinline +#else +#define REALINLINE inline +#endif #endif +#define reciprocal_zero(x) ((x) != 0.f ? 1.f / (x):0.f) +#define reciprocal_one(x) ((x) != 0.f ? 1.f / (x):1.f) + +//Control Scanline output +#define SOFTWARE_DRIVER_2_STEP_X 1 +#define SOFTWARE_DRIVER_2_STEP_Y 1 // null check necessary (burningvideo only) -#define reciprocal_zero(x) ((x) != 0.f ? 1.f / (x):0.f) -static inline float reciprocal_zero2(float x) { return x != 0.f ? 1.f / x : 0.f; } -#define reciprocal_one(x) ((x) != 0.f ? 1.f / (x):1.f) +#define fill_step_y(y) ((y) != 0.f ? (float)1.f / (y):0.f) +static inline float fill_step_x(float x) { return x != 0.f ? (float)SOFTWARE_DRIVER_2_STEP_X / x : 0.f; } + +#define interlace_control_bit 1 +#define interlace_control_mask ((1<> (interlace_control_bit-1) ) & 1) == (Interlaced.nr & 1)) ) +//#define interlace_scanline +#else +#define interlace_scanline +#define interlace_scanline_enabled +#endif + +#define scissor_test_y if ((~TL_Flag & TL_SCISSOR) || ((line.y >= Scissor.y0) & (line.y <= Scissor.y1))) +#define scissor_test_x if ((~TL_Flag & TL_SCISSOR) || ((i+xStart >= Scissor.x0) & (i+xStart <= Scissor.x1))) #define fill_convention_left(x) (s32) ceilf(x) #define fill_convention_right(x) ((s32) ceilf(x))-1 #define fill_convention_none(x) (s32) (x) +#define fill_convention_edge(x) (s32) floorf(fabsf(x)+0.f) //#define fill_convention_left(x) 65536 - int(65536.0f - x) //#define fill_convention_right(x) 65535 - int(65536.0f - x) @@ -157,7 +184,7 @@ static inline float reciprocal_zero2(float x) { return x != 0.f ? 1.f / x : 0.f; inline float reciprocal_zero_no(const float x) { - if (x*x <= 0.00001f) __debugbreak(); + if (x * x <= 0.00001f) __debugbreak(); return 1.f / x; } #else @@ -183,49 +210,49 @@ enum edge_test_flag #define fix_color_norm(x) x = (x+1) >> COLOR_MAX_LOG2 //! from 1 bit to 5 bit -#ifdef SOFTWARE_DRIVER_2_32BIT - #define fix_alpha_color_max(x) +#if defined(SOFTWARE_DRIVER_2_32BIT) +#define fix_alpha_color_max(x) #else - #define fix_alpha_color_max(x) if (x) x = (x << COLOR_MAX_LOG2) - 1 +#define fix_alpha_color_max(x) if (x) x = (x << COLOR_MAX_LOG2) - 1 #endif // Check windows #if _WIN32 || _WIN64 #if _WIN64 - #define ENV64BIT +#define ENV64BIT #else - #define ENV32BIT +#define ENV32BIT #endif #endif // Check GCC #if __GNUC__ #if __x86_64__ || __ppc64__ - #define ENV64BIT +#define ENV64BIT #else - #define ENV32BIT +#define ENV32BIT #endif #endif #if defined(ENV64BIT) && defined(BURNINGVIDEO_RENDERER_BEAUTIFUL) - typedef float ipoltype; +typedef float ipoltype; #else - typedef float ipoltype; +typedef float ipoltype; #endif #define ipol_lower_equal_0(n) ((n) <= (ipoltype)0.0) #define ipol_greater_0(n) ((n) > (ipoltype)0.0) #if (_MSC_VER > 1700 ) - #define burning_restrict __restrict +#define burning_restrict __restrict #else - #define burning_restrict +#define burning_restrict #endif /* if (condition) state |= mask; else state &= ~mask; */ -static inline void burning_setbit(size_t &state, int condition, size_t mask) +static inline void burning_setbit(size_t& state, int condition, size_t mask) { if (condition) state |= mask; else state &= ~mask; @@ -234,7 +261,7 @@ static inline void burning_setbit(size_t &state, int condition, size_t mask) /* if (condition) state |= m; else state &= ~m; */ -REALINLINE void burning_setbit32(unsigned int &state, int condition, const unsigned int mask) +REALINLINE void burning_setbit32(unsigned int& state, int condition, const unsigned int mask) { // 0, or any positive to mask //s32 conmask = -condition >> 31; @@ -246,44 +273,46 @@ REALINLINE void burning_setbit32(unsigned int &state, int condition, const unsig #define burning_create(s) burning_create_indirect(s) -#if defined(PATCH_SUPERTUX_8_0_1) -#define getData lock +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) #define snprintf_irr sprintf_s - -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR -#ifdef SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR -#define BURNING_MATERIAL_MAX_COLORS 2 -#else -#define BURNING_MATERIAL_MAX_COLORS 1 -#endif -#else -#define BURNING_MATERIAL_MAX_COLORS 0 -#endif - -#ifndef _IRR_OVERRIDE_ -#define _IRR_OVERRIDE_ /**/ -#endif - -#define fix_to_color fix_to_sample -#define fix4_to_color fix4_to_sample -#define vec4_to_fix getSample_color -#define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 +#define EVDF_DEPTH_CLAMP 43 +#define E_CUBE_SURFACE int +#define ECFN_DISABLED 0 namespace irr { + namespace video { - REALINLINE void memcpy32_small(void * dest, const void *source, size_t bytesize) - { - size_t c = bytesize >> 2; - - do + //! Enum for the flags of clear buffer + enum E_CLEAR_BUFFER_FLAG { - ((unsigned int *)dest)[c - 1] = ((unsigned int *)source)[c - 1]; - } while (--c); + ECBF_NONE = 0, + ECBF_COLOR = 1, + ECBF_DEPTH = 2, + ECBF_STENCIL = 4, + ECBF_ALL = ECBF_COLOR | ECBF_DEPTH | ECBF_STENCIL + }; + //! For SMaterial.ZWriteEnable + enum E_ZWRITE + { + EZW_OFF = 0, + EZW_AUTO, + EZW_ON + }; } +} +#endif // PATCH_SUPERTUX_8_0_1_with_1_9_0 -} // namespace irr -#endif // #if defined(PATCH_SUPERTUX_8_0_1) +//! Size of a static C-style array. +#define array_size(_arr) ((sizeof(_arr)/sizeof(*_arr))) +//! Compiler Align +#if defined(_MSC_VER) +#define ALIGN(x) __declspec(align(x)) +#elif defined(__GNUC__) +#define ALIGN(x) __attribute__ ((aligned(x))) +#else +#define ALIGN(x) +#endif #endif // __S_VIDEO_2_SOFTWARE_COMPILE_CONFIG_H_INCLUDED__ diff --git a/source/Irrlicht/SoftwareDriver2_helper.h b/source/Irrlicht/SoftwareDriver2_helper.h index 433ea457..83168c94 100644 --- a/source/Irrlicht/SoftwareDriver2_helper.h +++ b/source/Irrlicht/SoftwareDriver2_helper.h @@ -22,7 +22,7 @@ namespace irr // supporting different packed pixel needs many defines... -#ifdef SOFTWARE_DRIVER_2_32BIT +#if defined(SOFTWARE_DRIVER_2_32BIT) typedef u32 tVideoSample; typedef u32 tStencilSample; @@ -40,8 +40,8 @@ namespace irr #define COLOR_MAX_LOG2 8 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF - #define VIDEO_SAMPLE_GRANULARITY (unsigned)2 - + #define SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY (unsigned)2 + #define SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY (unsigned)2 #else typedef u16 tVideoSample; typedef u8 tStencilSample; @@ -59,7 +59,8 @@ namespace irr #define COLOR_MAX 0x1F #define COLOR_MAX_LOG2 5 #define COLOR_BRIGHT_WHITE 0xFFFF - #define VIDEO_SAMPLE_GRANULARITY (unsigned)1 + #define SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY (unsigned)1 + #define SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY (unsigned)1 #endif @@ -140,6 +141,19 @@ inline void memset16(void * dest, const u16 value, size_t bytesize) } } +//! memset interleaved +inline void memset32_interlaced(void* dest, const u32 value, size_t pitch,u32 height,const interlaced_control Interlaced) +{ + if (Interlaced.bypass) return memset32(dest, value, pitch * height); + + u8* dst = (u8*)dest; + interlace_scanline_data line; + for (line.y = 0; line.y < height; line.y += SOFTWARE_DRIVER_2_STEP_Y) + { + interlace_scanline_enabled memset32(dst, value, pitch); + dst += pitch; + } +} // byte-align structures #include "irrpack.h" @@ -577,7 +591,7 @@ REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y) */ REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y) { -#ifdef SOFTWARE_DRIVER_2_32BIT +#if SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT == ECF_A8R8G8B8 return (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu) (FIX_POINT_PRE + 4); #else return (x * (y+ FIX_POINT_ONE)) >> (FIX_POINT_PRE + 5); @@ -598,7 +612,7 @@ REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y) REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y) { -#ifdef SOFTWARE_DRIVER_2_32BIT +#if SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT == ECF_A8R8G8B8 tFixPoint a = (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 2); #else tFixPoint a = (x * (y + FIX_POINT_ONE)) >> (FIX_POINT_PRE + 3); @@ -608,17 +622,6 @@ REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y) } -#if 0 -#define imulFix_tex1(x,y) ((((tFixPointu)x >> 2) * ((tFixPointu)y >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 4)) -#define imulFix_tex2(x,y) ((((tFixPointu)x >> 2) * ((tFixPointu)y >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 3)) - -#ifdef SOFTWARE_DRIVER_2_32BIT -#define imulFix_tex4(x,y) ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 ) -#else -#define imulFix_tex4(x,y) ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) ) -#endif -#endif - /*! clamp FixPoint to maxcolor in FixPoint, min(a,COLOR_MAX) */ @@ -831,7 +834,7 @@ static inline tVideoSample getTexel_plain ( const sInternalTexture* t, const tFi size_t ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY ); // texel return *((tVideoSample*)( (u8*) t->data + ofs )); @@ -845,7 +848,7 @@ inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, size_t ofs; ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY ); // texel tVideoSample t00; @@ -865,7 +868,7 @@ inline void getTexel_fix(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, size_t ofs; ofs = (((ty+ FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; - ofs |= ((tx+ FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + ofs |= ((tx+ FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); // texel tVideoSample t00; @@ -886,7 +889,7 @@ static REALINLINE void getTexel_fix ( tFixPoint &a, size_t ofs; ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY ); // texel tVideoSample t00; @@ -913,7 +916,7 @@ static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint & size_t ofs; ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; - ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); // texel tVideoSample t00; @@ -937,8 +940,8 @@ static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint & //wraps positive (ignoring negative) o0 = (((ty)& t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; o1 = (((ty + FIX_POINT_ONE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; - o2 = ((tx)& t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); - o3 = ((tx + FIX_POINT_ONE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o2 = ((tx)& t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); t00 = *((tVideoSample*)((u8*)t->data + (o0 + o2))); r00 = (t00 & MASK_R) >> SHIFT_R; @@ -1001,7 +1004,7 @@ static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint & //nearest neighbor size_t ofs; ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; - ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); tVideoSample t00; t00 = *((tVideoSample*)((u8*)tex->data + ofs)); @@ -1029,8 +1032,8 @@ static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint & size_t o0, o1, o2, o3; o0 = (((ty) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; - o2 = ((tx)& tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); - o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o2 = ((tx)& tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); t[0] = *((tVideoSample*)((u8*)tex->data + (o0 + o2))); t[1] = *((tVideoSample*)((u8*)tex->data + (o0 + o3))); @@ -1072,8 +1075,8 @@ static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint & o0 = (((ty)& tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; - o2 = ((tx)& tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); - o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o2 = ((tx)& tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); t00 = *((tVideoSample*)((u8*)tex->data + (o0 + o2))); a00 = (t00 & MASK_A) >> SHIFT_A; @@ -1144,7 +1147,7 @@ static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint & { size_t ofs; ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; - ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); // texel const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs)); @@ -1160,7 +1163,7 @@ static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint & { size_t ofs; ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; - ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY); // texel const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs)); @@ -1233,8 +1236,6 @@ static inline int tiny_isequal(const char *s1, const char *s2, size_t n) } #define tiny_istoken(a, b) tiny_isequal(a,b,sizeof(a)-1) != 0 -//! Size of a static C-style array. -#define array_size(_arr) ((sizeof(_arr)/sizeof(*_arr))) } // end namespace irr diff --git a/source/Irrlicht/burning_shader_compile_fragment_start.h b/source/Irrlicht/burning_shader_compile_fragment_start.h index 64a84633..15306449 100644 --- a/source/Irrlicht/burning_shader_compile_fragment_start.h +++ b/source/Irrlicht/burning_shader_compile_fragment_start.h @@ -40,7 +40,7 @@ void burning_shader_class::burning_shader_fragment() return; // slopes - const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + const f32 invDeltaX = fill_step_x(line.x[1] - line.x[0]); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -96,9 +96,9 @@ void burning_shader_class::burning_shader_fragment() tFixPoint r1, g1, b1; #endif - for (s32 i = 0; i <= dx; ++i) + for (s32 i = 0; i <= dx; i+= SOFTWARE_DRIVER_2_STEP_X) { - if ((0 == EdgeTestPass) & i) break; + if ((0 == EdgeTestPass) & (i > line.x_edgetest)) break; #ifdef CMP_Z if (line.z[0] < z[i]) diff --git a/source/Irrlicht/burning_shader_compile_triangle.h b/source/Irrlicht/burning_shader_compile_triangle.h index aa588581..5594b989 100644 --- a/source/Irrlicht/burning_shader_compile_triangle.h +++ b/source/Irrlicht/burning_shader_compile_triangle.h @@ -139,8 +139,10 @@ void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, con #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); + // rasterize the edge scanlines - for (line.y = yStart; line.y <= yEnd; ++line.y) + for (line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -171,6 +173,7 @@ void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, con #endif // render a scanline + interlace_scanline (this->*fragmentShader) (); if (EdgeTestPass & edge_test_first_line) break; @@ -265,7 +268,6 @@ void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, con yEnd = fill_convention_right(c->Pos.y); #ifdef SUBTEXEL - subPixel = ((f32)yStart) - b->Pos.y; // correct to pixel center @@ -299,8 +301,10 @@ void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, con #endif + line.x_edgetest = fill_convention_edge(scan.slopeX[scan.left]); + // rasterize the edge scanlines - for (line.y = yStart; line.y <= yEnd; ++line.y) + for (line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; @@ -331,6 +335,7 @@ void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, con #endif // render a scanline + interlace_scanline (this->*fragmentShader) (); if (EdgeTestPass & edge_test_first_line) break; diff --git a/source/Irrlicht/libpng/ANNOUNCE b/source/Irrlicht/libpng/ANNOUNCE index e427fd4a..33f9b05d 100644 --- a/source/Irrlicht/libpng/ANNOUNCE +++ b/source/Irrlicht/libpng/ANNOUNCE @@ -1,48 +1,47 @@ -Libpng 1.6.23 - June 9, 2016 +libpng 1.6.37 - April 14, 2019 +============================== -This is a public release of libpng, intended for use in production codes. +This is a public release of libpng, intended for use in production code. -Files available for download: -Source files with LF line endings (for Unix/Linux) and with a -"configure" script +Files available for download +---------------------------- - libpng-1.6.23.tar.xz (LZMA-compressed, recommended) - libpng-1.6.23.tar.gz +Source files with LF line endings (for Unix/Linux): -Source files with CRLF line endings (for Windows), without the -"configure" script + * libpng-1.6.37.tar.xz (LZMA-compressed, recommended) + * libpng-1.6.37.tar.gz - lpng1623.7z (LZMA-compressed, recommended) - lpng1623.zip +Source files with CRLF line endings (for Windows): + + * lp1637.7z (LZMA-compressed, recommended) + * lp1637.zip Other information: - libpng-1.6.23-README.txt - libpng-1.6.23-LICENSE.txt - libpng-1.6.23-*.asc (armored detached GPG signatures) + * README.md + * LICENSE.md + * AUTHORS.md + * TRADEMARK.md -Changes since the last public release (1.6.22): - Stop a potential memory leak in png_set_tRNS() (Bug report by Ted Ying). - Fixed the progressive reader to handle empty first IDAT chunk properly - (patch by Timothy Nikkel). This bug was introduced in libpng-1.6.0 and - only affected the libpng16 branch. - Added tests in pngvalid.c to check zero-length IDAT chunks in various - positions. Fixed the sequential reader to handle these more robustly - (John Bowler). - Corrected progressive read input buffer in pngvalid.c. The previous version - the code invariably passed just one byte at a time to libpng. The intent - was to pass a random number of bytes in the range 0..511. - Moved sse2 prototype from pngpriv.h to contrib/intel/intel_sse.patch. - Added missing ")" in pngerror.c (Matt Sarrett). - Fixed undefined behavior in png_push_save_buffer(). Do not call - memcpy() with a null source, even if count is zero (Leon Scroggins III). - Fixed bad link to RFC2083 in png.5 (Nikola Forro). +Changes since the previous public release (version 1.6.36) +---------------------------------------------------------- -(subscription required; visit + * Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free. + * Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette. + * Fixed a memory leak in pngtest.c. + * Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in + contrib/pngminus; refactor. + * Changed the license of contrib/pngminus to MIT; refresh makefile and docs. + (Contributed by Willem van Schaik) + * Fixed a typo in the libpng license v2. + (Contributed by Miguel Ojeda) + * Added makefiles for AddressSanitizer-enabled builds. + * Cleaned up various makefiles. + + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net - -Glenn R-P +to subscribe. diff --git a/source/Irrlicht/libpng/AUTHORS b/source/Irrlicht/libpng/AUTHORS new file mode 100644 index 00000000..aa940bd1 --- /dev/null +++ b/source/Irrlicht/libpng/AUTHORS @@ -0,0 +1,45 @@ +PNG REFERENCE LIBRARY AUTHORS +============================= + +This is the list of PNG Reference Library ("libpng") Contributing +Authors, for copyright and licensing purposes. + + * Andreas Dilger + * Cosmin Truta + * Dave Martindale + * Eric S. Raymond + * Gilles Vollant + * Glenn Randers-Pehrson + * Greg Roelofs + * Guy Eric Schalnat + * James Yu + * John Bowler + * Kevin Bracey + * Magnus Holmgren + * Mandar Sahastrabuddhe + * Mans Rullgard + * Matt Sarett + * Mike Klein + * Paul Schmidt + * Sam Bushell + * Samuel Williams + * Simon-Pierre Cadieux + * Tim Wegner + * Tom Lane + * Tom Tanner + * Vadim Barkov + * Willem van Schaik + * Zhijie Liang + * Arm Holdings + - Richard Townsend + * Google Inc. + - Matt Sarett + - Mike Klein + +The build projects, the build scripts, the test scripts, and other +files in the "projects", "scripts" and "tests" directories, have other +copyright owners, but are released under the libpng license. + +Some files in the "contrib" directory, and some tools-generated files +that are distributed with libpng, have other copyright owners, and are +released under other open source licenses. diff --git a/source/Irrlicht/libpng/CHANGES b/source/Irrlicht/libpng/CHANGES index 55a4d469..abd63da4 100644 --- a/source/Irrlicht/libpng/CHANGES +++ b/source/Irrlicht/libpng/CHANGES @@ -1,4 +1,3 @@ -#if 0 CHANGES - changes for libpng version 0.1 [March 29, 1995] @@ -593,7 +592,7 @@ Version 1.0.5e [November 30, 1999] with trailing compressed parts easier in the future, and added new functions png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). - NOTE: Applications that write text chunks MUST define png_text->lang + NOTE: Applications that write text chunks MUST define png_text->lang before calling png_set_text(). It must be set to NULL if you want to write tEXt or zTXt chunks. If you want your application to be able to run with older versions of libpng, use @@ -833,7 +832,7 @@ Version 1.0.7beta11 [May 7, 2000] Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. @@ -1454,7 +1453,7 @@ Version 1.2.6beta4 [July 28, 2004] sequential read support. Added some "#if PNG_WRITE_SUPPORTED" blocks. Added #ifdef to remove some redundancy in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. + Use png_malloc instead of png_zalloc to allocate the palette. Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS(). @@ -3259,7 +3258,7 @@ Version 1.5.2beta01 [February 13, 2011] Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the old VisualC++ preprocessor. Turned on interlace handling in png_read_png(). - Fixed gcc pendantic warnings. + Fixed gcc pedantic warnings. Handle longjmp in Cygwin. Fixed png_get_current_row_number() in the interlaced case. Cleaned up ALPHA flags and transformations. @@ -3359,7 +3358,7 @@ Version 1.5.3beta05 [May 6, 2011] Pass "" instead of '\0' to png_default_error() in png_err(). This mistake was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte - optimization configureable. + optimization configurable. IDAT compression failed if preceded by a compressed text chunk (bug introduced in libpng-1.5.3beta01-02). This was because the attempt to reset the zlib stream in png_write_IDAT happened after the first IDAT @@ -3643,7 +3642,7 @@ Version 1.5.6beta05 [October 12, 2011] Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. Version 1.5.6beta06 [October 17, 2011] - Removed two redundant tests for unitialized row. + Removed two redundant tests for uninitialized row. Fixed a relatively harmless memory overwrite in compressed text writing with a 1 byte zlib buffer. Add ability to call png_read_update_info multiple times to pngvalid.c. @@ -3689,7 +3688,7 @@ Version 1.5.7beta01 [November 4, 2011] crash. The pngmem.c implementation of png_malloc() included a cast to png_size_t which would fail on large allocations on 16-bit systems. Fix for the preprocessor of the Intel C compiler. The preprocessor - splits adjacent @ signs with a space; this changes the concatentation + splits adjacent @ signs with a space; this changes the concatenation token from @-@-@ to PNG_JOIN; that should work with all compiler preprocessors. Paeth filter speed improvements from work by Siarhei Siamashka. This @@ -3735,7 +3734,7 @@ Version 1.5.7beta03 [November 17, 2011] gray (on palette) itself. Fixes for C++ compilation using g++ When libpng source is compiled using g++. The compiler imposes C++ rules on the C source; thus it - is desireable to make the source work with either C or C++ rules + is desirable to make the source work with either C or C++ rules without throwing away useful error information. This change adds png_voidcast to allow C semantic (void*) cases or the corresponding C++ static_cast operation, as appropriate. @@ -4061,7 +4060,7 @@ Version 1.6.0beta17 [March 10, 2012] possible to call png_inflate() incrementally. A warning is no longer issued if the language tag or translated keyword in the iTXt chunk has zero length. - If benign errors are disabled use maximum window on ancilliary inflate. + If benign errors are disabled use maximum window on ancillary inflate. This works round a bug introduced in 1.5.4 where compressed ancillary chunks could end up with a too-small windowBits value in the deflate header. @@ -4176,7 +4175,7 @@ Version 1.6.0beta27 [August 11, 2012] declared even though the functions are never actually defined. This change provides a dummy definition so that the declarations work, yet any implementation will fail to compile because of an incomplete type. - Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of + Re-eliminated the use of strcpy() in pngtest.c. An unnecessary use of strcpy() was accidentally re-introduced in libpng16; this change replaces it with strncpy(). Eliminated use of png_sizeof(); use sizeof() instead. @@ -4309,7 +4308,7 @@ Version 1.6.0beta31 [November 1, 2012] resulting in VS2010 having to update the files. Removed non-working ICC profile support code that was mostly added to libpng-1.6.0beta29 and beta30. There was too much code for too little - gain; implementing full ICC color correction may be desireable but is left + gain; implementing full ICC color correction may be desirable but is left up to applications. Version 1.6.0beta32 [November 25, 2012] @@ -4592,7 +4591,7 @@ Version 1.6.3beta07 [June 8, 2013] the optimizations ('check' vs 'api') are exposed in the public header files except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the decision about whether or not to use the optimizations. - Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage. + Protect symbol prefixing against CC/CPPFLAGS/CFLAGS usage. Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test on __ARM_NEON__ from configure time to compile time. This breaks symbol prefixing because the definition of the special png_init_filter_functions @@ -5596,11 +5595,515 @@ Version 1.6.23rc02 [June 4, 2016] Version 1.6.23 [June 9, 2016] Fixed bad link to RFC2083 in png.5 (Nikola Forro). -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 +Version 1.6.24beta01 [June 11, 2016] + Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro + is not used within libpng, but is used in some of the examples. -Glenn R-P -#endif +Version 1.6.24beta02 [June 23, 2016] + Correct filter heuristic overflow handling. This was broken when the + write filter code was moved out-of-line; if there is a single filter and + the heuristic sum overflows the calculation of the filtered line is not + completed. In versions prior to 1.6 the code was duplicated in-line + and the check not performed, so the filter operation completed; however, + in the multi-filter case where the sum is performed the 'none' filter would + be selected if all the sums overflowed, even if it wasn't in the filter + list. The fix to the first problem is simply to provide PNG_SIZE_MAX as + the current lmins sum value; this means the sum can never exceed it and + overflows silently. A reasonable compiler that does choose to inline + the code will simply eliminate the sum check. + The fix to the second problem is to use high precision arithmetic (this is + implemented in 1.7), however a simple safe fix here is to chose the lowest + numbered filter in the list from png_set_filter (this only works if the + first problem is also fixed) (John Bowler). + Use a more efficient absolute value calculation on SSE2 (Matthieu Darbois). + Fixed the case where PNG_IMAGE_BUFFER_SIZE can overflow in the application + as a result of the application using an increased 'row_stride'; previously + png_image_finish_read only checked for overflow on the base calculation of + components. (I.e. it checked for overflow of a 32-bit number on the total + number of pixel components in the output format, not the possibly padded row + length and not the number of bytes, which for linear formats is twice the + number of components.) + MSVC does not like '-(unsigned)', so replaced it with 0U-(unsigned) + MSVC does not like (uInt) = -(unsigned) (i.e. as an initializer), unless + the conversion is explicitly invoked by a cast. + Put the SKIP definition in the correct place. It needs to come after the + png.h include (see all the other .c files in contrib/libtests) because it + depends on PNG_LIBPNG_VER. + Removed the three compile warning options from the individual project + files into the zlib.props globals. It increases the warning level from 4 + to All and adds a list of the warnings that need to be turned off. This is + semi-documentary; the intent is to tell libpng users which warnings have + been examined and judged non-fixable at present. The warning about + structure padding is fixable, but it would be a significant change (moving + structure members around). + +Version 1.6.24beta03 [July 4, 2016] + Optimized absolute value calculation in filter selection, similar to + code in the PAETH decoder in pngrutil.c. Build with PNG_USE_ABS to + use this. + Added pngcp to the build together with a pngcp.dfa configuration test. + Added high resolution timing to pngcp. + Added "Common linking failures" section to INSTALL. + Relocated misplaced #endif in png.c sRGB profile checking. + Fixed two Coverity issues in pngcp.c. + +Version 1.6.24beta04 [July 8, 2016] + Avoid filter-selection heuristic sum calculations in cases where only one + filter is a candidate for selection. This trades off code size (added + private png_setup_*_row_only() functions) for speed. + +Version 1.6.24beta05 [July 13, 2016] + Fixed some indentation to comply with our coding style. + Added contrib/tools/reindent. + +Version 1.6.24beta06 [July 18, 2016] + Fixed more indentation to comply with our coding style. + Eliminated unnecessary tests of boolean png_isaligned() vs 0. + +Version 1.6.24rc01 [July 25, 2016] + No changes. + +Version 1.6.24rc02 [August 1, 2016] + Conditionally compile SSE2 headers in contrib/intel/intel_sse.patch + Conditionally compile png_decompress_chunk(). + +Version 1.6.24rc03 [August 2, 2016] + Conditionally compile ARM_NEON headers in pngpriv.h + Updated contrib/intel/intel_sse.patch + +Version 1.6.24[August 4, 2016] + No changes. + +Version 1.6.25beta01 [August 12, 2016] + Reject oversized iCCP profile immediately. + Cleaned up PNG_DEBUG compile of pngtest.c. + Conditionally compile png_inflate(). + +Version 1.6.25beta02 [August 18, 2016] + Don't install pngcp; it conflicts with pngcp in the pngtools package. + Minor editing of INSTALL, (whitespace, added copyright line) + +Version 1.6.25rc01 [August 24, 2016] + No changes. + +Version 1.6.25rc02 [August 29, 2016] + Added MIPS support (Mandar Sahastrabuddhe ). + Only the UP filter is currently implemented. + +Version 1.6.25rc03 [August 29, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation. + +Version 1.6.25rc04 [August 30, 2016] + Added MIPS support for SUB, AVG, and PAETH filters (Mandar Sahastrabuddhe). + +Version 1.6.25rc05 [August 30, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation update.. + +Version 1.6.25 [September 1, 2016] + No changes. + +Version 1.6.26beta01 [September 26, 2016] + Fixed handling zero length IDAT in pngfix (bug report by Agostino Sarubbo, + bugfix by John Bowler). + Do not issue a png_error() on read in png_set_pCAL() because png_handle_pCAL + has allocated memory that libpng needs to free. + Conditionally compile png_set_benign_errors() in pngread.c and pngtest.c + Issue a png_benign_error instead of a png_error on ADLER32 mismatch + while decoding compressed data chunks. + Changed PNG_ZLIB_VERNUM to ZLIB_VERNUM in pngpriv.h, pngstruct.h, and + pngrutil.c. + If CRC handling of critical chunks has been set to PNG_CRC_QUIET_USE, + ignore the ADLER32 checksum in the IDAT chunk as well as the chunk CRCs. + Issue png_benign_error() on ADLER32 checksum mismatch instead of png_error(). + Add tests/badcrc.png and tests/badadler.png to tests/pngtest. + Merged pngtest.c with libpng-1.7.0beta84/pngtest.c + +Version 1.6.26beta02 [October 1, 2016] + Updated the documentation about CRC and ADLER32 handling. + Quieted 117 warnings from clang-3.8 in pngtrans.c, pngread.c, + pngwrite.c, pngunknown.c, and pngvalid.c. + Quieted 58 (out of 144) -Wconversion compiler warnings by changing + flag definitions in pngpriv.h from 0xnnnn to 0xnnnnU and trivial changes + in png.c, pngread.c, and pngwutil.c. + +Version 1.6.26beta03 [October 2, 2016] + Removed contrib/libtests/*.orig and *.rej that slipped into the tarballs. + Quieted the 86 remaining -Wconversion compiler warnings by + revising the png_isaligned() macro and trivial changes in png.c, + pngerror.c, pngget.c, pngmem.c, pngset.c, pngrtran.c, pngrutil.c, + pngwtran.c, pngwrite.c, and pngwutil.c. + +Version 1.6.26beta04 [October 3, 2016] + Quieted (bogus?) clang warnings about "absolute value has no effect" + when PNG_USE_ABS is defined. + Fixed offsets in contrib/intel/intel_sse.patch + +Version 1.6.26beta05 [October 6, 2016] + Changed integer constant 4294967294 to unsigned 4294967294U in pngconf.h + to avoid a signed/unsigned compare in the preprocessor. + +Version 1.6.26beta06 [October 7, 2016] + Use zlib-1.2.8.1 inflateValidate() instead of inflateReset2() to + optionally avoid ADLER32 evaluation. + +Version 1.6.26rc01 [October 12, 2016] + No changes. + +Version 1.6.26 [October 20, 2016] + Cosmetic change, "ptr != 0" to "ptr != NULL" in png.c and pngrutil.c + Despammed email addresses (replaced "@" with " at "). + +Version 1.6.27beta01 [November 2, 2016] + Restrict the new ADLER32-skipping to IDAT chunks. It broke iCCP chunk + handling: an erroneous iCCP chunk would throw a png_error and reject the + entire PNG image instead of rejecting just the iCCP chunk with a warning, + if built with zlib-1.2.8.1. + +Version 1.6.27rc01 [December 27, 2016] + Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes + an endless loop when handling erroneous ADLER32 checksums; bug + introduced in libpng-1.6.26. + Removed the use of a macro containing the pre-processor 'defined' + operator. It is unclear whether this is valid; a macro that + "generates" 'defined' is not permitted, but the use of the word + "generates" within the C90 standard seems to imply more than simple + substitution of an expression itself containing a well-formed defined + operation. + Added ARM support to CMakeLists.txt (Andreas Franek). + +Version 1.6.27 [December 29, 2016] + Fixed a potential null pointer dereference in png_set_text_2() (bug report + and patch by Patrick Keshishian, CVE-2016-10087). + +Version 1.6.28rc01 [January 3, 2017] + Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna). + Added option to Cmake build allowing a custom location of zlib to be + specified in a scenario where libpng is being built as a subproject + alongside zlib by another project (Sam Serrels). + Changed png_ptr->options from a png_byte to png_uint_32, to accommodate + up to 16 options. + +Version 1.6.28rc02 [January 4, 2017] + Added "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + +Version 1.6.28rc03 [January 4, 2017] + Backed out the SSE optimization and last CMakeLists.txt to allow time for QA. + +Version 1.6.28 [January 5, 2017] + No changes. + +Version 1.6.29beta01 [January 12, 2017] + Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt). + +Version 1.6.29beta02 [February 22, 2017] + Avoid conditional directives that break statements in pngrutil.c (Romero + Malaquias) + The contrib/examples/pngtopng.c recovery code was in the wrong "if" + branches; the comments were correct. + Added code for PowerPC VSX optimisation (Vadim Barkov). + +Version 1.6.29beta03 [March 1, 2017] + Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer). + Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c + because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1, + as suggested in zlib FAQ, item 24. + Suppress clang warnings about implicit sign changes in png.c + +Version 1.6.29 [March 16, 2017] + No changes. + +Version 1.6.30beta01 [April 1, 2017] + Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in + makefile.linux and makefile.solaris-x86 (Cosmin). + Revised documentation of png_get_error_ptr() in the libpng manual. + Silence clang -Wcomma and const drop warnings (Viktor Szakats). + Update Sourceforge URLs in documentation (https instead of http). + +Version 1.6.30beta02 [April 22, 2017] + Document need to check for integer overflow when allocating a pixel + buffer for multiple rows in contrib/gregbook, contrib/pngminus, + example.c, and in the manual (suggested by Jaeseung Choi). This + is similar to the bug reported against pngquant in CVE-2016-5735. + Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation. + +Version 1.6.30beta03 [May 22, 2017] + Check for integer overflow in contrib/visupng and contrib/tools/genpng. + Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt. + Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt. + Fix some URL in documentation. + +Version 1.6.30beta04 [June 7, 2017] + Avoid writing an empty IDAT when the last IDAT exactly fills the + compression buffer (bug report by Brian Baird). This bug was + introduced in libpng-1.6.0. + +Version 1.6.30rc01 [June 14, 2017] + No changes. + +Version 1.6.30rc02 [June 25, 2017] + Update copyright year in pnglibconf.h, make ltmain.sh executable. + Add a reference to the libpng.download site in README. + +Version 1.6.30 [June 28, 2017] + No changes. + +Version 1.6.31beta01 [July 5, 2017] + Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it; + bug report by Michael Felt). + Revised pngpriv.h to work around failure to compile arm/filter_neon.S + ("typedef" directive is unrecognized by the assembler). The problem + was introduced in libpng-1.6.30beta01. + Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx). + Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish). + +Version 1.6.31beta02 [July 8, 2017] + Added instructions for disabling hardware optimizations in INSTALL. + Added "--enable-hardware-optimizations" configuration flag to enable + or disable all hardware optimizations with one flag. + +Version 1.6.31beta03 [July 9, 2017] + Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms. + Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent + possible integer overflow (Bug report by John Bowler). + Quieted "declaration after statement" warnings in intel/filter_sse2.c. + Added scripts/makefile-linux-opt, which has hardware optimizations enabled. + +Version 1.6.31beta04 [July 11, 2017] + Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when + integers appear on both sides of a compare. Worked around the others by + forcing the strict-overflow setting in the relevant functions to a level + where they are not reported (John Bowler). + Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like + the space. + Worked around some C-style casts from (void*) because g++ 5.4.0 objects + to them. + Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint + overflow' check that is on by default with -Wall -Wextra. + +Version 1.6.31beta05 [July 13, 2017] + Added eXIf chunk support. + +Version 1.6.31beta06 [July 17, 2017] + Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm + tags) to pngtest.png. + +Version 1.6.31beta07 [July 18, 2017] + Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning. + +Version 1.6.31rc01 [July 19, 2017] + No changes. + +Version 1.6.31rc02 [July 25, 2017] + Fixed typo in example.c (png_free_image should be png_image_free) (Bug + report by John Smith) + +Version 1.6.31 [July 27, 2017] + No changes. + +Version 1.6.32beta01 [July 31, 2017] + Avoid possible NULL dereference in png_handle_eXIf when benign_errors + are allowed. Avoid leaking the input buffer "eXIf_buf". + Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif + to arguments for png_get_eXIf() and png_set_eXIf(). + Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in + pngwrite.c, and made various other fixes to png_write_eXIf(). + Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and + png_set_eXIf_1(), respectively, to avoid breaking API compatibility + with libpng-1.6.31. + +Version 1.6.32beta02 [August 1, 2017] + Updated contrib/libtests/pngunknown.c with eXIf chunk. + +Version 1.6.32beta03 [August 2, 2017] + Initialized btoa[] in pngstest.c + Stop memory leak when returning from png_handle_eXIf() with an error + (Bug report from the OSS-fuzz project). + +Version 1.6.32beta04 [August 2, 2017] + Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Update libpng.3 and libpng-manual.txt about eXIf functions. + +Version 1.6.32beta05 [August 2, 2017] + Restored png_get_eXIf() and png_set_eXIf() to maintain API compatibility. + +Version 1.6.32beta06 [August 2, 2017] + Removed png_get_eXIf_1() and png_set_eXIf_1(). + +Version 1.6.32beta07 [August 3, 2017] + Check length of all chunks except IDAT against user limit to fix an + OSS-fuzz issue (Fixes CVE-2017-12652). + +Version 1.6.32beta08 [August 3, 2017] + Check length of IDAT against maximum possible IDAT size, accounting + for height, rowbytes, interlacing and zlib/deflate overhead. + Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) + does not work (the eXIf chunk data can contain zeroes). + +Version 1.6.32beta09 [August 3, 2017] + Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, + no longer using deprecated cmake LOCATION feature (Clifford Yapp). + Fixed five-byte error in the calculation of IDAT maximum possible size. + +Version 1.6.32beta10 [August 5, 2017] + Moved chunk-length check into a png_check_chunk_length() private + function (Suggested by Max Stepin). + Moved bad pngs from tests to contrib/libtests/crashers + Moved testing of bad pngs into a separate tests/pngtest-badpngs script + Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL + in the output but PASS for the libpng test. + Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). + Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the + num_exif argument to png_get_eXIf_1() (Github Issue 171). + +Version 1.6.32beta11 [August 7, 2017] + Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). + Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. + Make pngtest --strict, --relax, --xfail options imply -m (multiple). + Removed unused chunk_name parameter from png_check_chunk_length(). + Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. + Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. + Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. + Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. + Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account + for the minimum 'deflate' stream, and relocate the test to a point + after the keyword has been read. + Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". + +Version 1.6.32rc01 [August 18, 2017] + Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, + one for each known chunk type, with length = 2GB-1. + Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts + in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, + and 162707). + Renamed chunks in contrib/testpngs/crashers to avoid having files whose + names differ only in case; this causes problems with some platforms + (github issue #172). + +Version 1.6.32rc02 [August 22, 2017] + Added contrib/oss-fuzz directory which contains files used by the oss-fuzz + project (https://github.com/google/oss-fuzz/tree/master/projects/libpng). + +Version 1.6.32 [August 24, 2017] + No changes. + +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of them caused test failures. + +Version 1.6.35beta01 [March 6, 2018] + Restored 21 of the contrib/pngsuite/i*.png, which do not cause test + failures. Placed the remainder in contrib/pngsuite/interlaced/i*.png. + Added calls to png_set_*() transforms commonly used by browsers to + the fuzzer. + Removed some unnecessary brackets in pngrtran.c + Fixed miscellaneous typos (Patch by github user "luzpaz"). + Change "ASM C" to "C ASM" in CMakeLists.txt + Fixed incorrect handling of bKGD chunk in sub-8-bit files (Cosmin) + Added hardware optimization directories to zip and 7z distributions. + Fixed incorrect bitmask for options. + Fixed many spelling typos. + +Version 1.6.35beta02 [March 28, 2018] + Make png_get_iCCP consistent with man page (allow compression-type argument + to be NULL, bug report by Lenard Szolnoki). + +Version 1.6.35 [July 15, 2018] + Replaced the remaining uses of png_size_t with size_t (Cosmin) + Fixed the calculation of row_factor in png_check_chunk_length + (reported by Thuan Pham in SourceForge issue #278) + Added missing parentheses to a macro definition + (suggested by "irwir" in GitHub issue #216) + +Version 1.6.36 [December 1, 2018] + Optimized png_do_expand_palette for ARM processors. + Improved performance by around 10-22% on a recent ARM Chromebook. + (Contributed by Richard Townsend, ARM Holdings) + Fixed manipulation of machine-specific optimization options. + (Contributed by Vicki Pfau) + Used memcpy instead of manual pointer arithmetic on Intel SSE2. + (Contributed by Samuel Williams) + Fixed build errors with MSVC on ARM64. + (Contributed by Zhijie Liang) + Fixed detection of libm in CMakeLists. + (Contributed by Cameron Cawley) + Fixed incorrect creation of pkg-config file in CMakeLists. + (Contributed by Kyle Bentley) + Fixed the CMake build on Windows MSYS by avoiding symlinks. + Fixed a build warning on OpenBSD. + (Contributed by Theo Buehler) + Fixed various typos in comments. + (Contributed by "luz.paz") + Raised the minimum required CMake version from 3.0.2 to 3.1. + Removed yet more of the vestigial support for pre-ANSI C compilers. + Removed ancient makefiles for ancient systems that have been broken + across all previous libpng-1.6.x versions. + Removed the Y2K compliance statement and the export control + information. + Applied various code style and documentation fixes. + +Version 1.6.37 [April 14, 2019] + Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free. + Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette. + Fixed a memory leak in pngtest.c. + Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in + contrib/pngminus; refactor. + Changed the license of contrib/pngminus to MIT; refresh makefile and docs. + (Contributed by Willem van Schaik) + Fixed a typo in the libpng license v2. + (Contributed by Miguel Ojeda) + Added makefiles for AddressSanitizer-enabled builds. + Cleaned up various makefiles. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe. diff --git a/source/Irrlicht/libpng/CMakeLists.txt b/source/Irrlicht/libpng/CMakeLists.txt index ddc796b8..73668ccd 100644 --- a/source/Irrlicht/libpng/CMakeLists.txt +++ b/source/Irrlicht/libpng/CMakeLists.txt @@ -1,58 +1,52 @@ # CMakeLists.txt -# Copyright (C) 2007,2009-2016 Glenn Randers-Pehrson +# Copyright (C) 2018 Cosmin Truta +# Copyright (C) 2007,2009-2018 Glenn Randers-Pehrson # Written by Christian Ehrlicher, 2007 # Revised by Roger Lowman, 2009-2010 -# Revised by Clifford Yapp, 2011-2012 +# Revised by Clifford Yapp, 2011-2012,2017 # Revised by Roger Leigh, 2016 +# Revised by Andreas Franek, 2016 +# Revised by Sam Serrels, 2017 +# Revised by Vadim Barkov, 2017 +# Revised by Vicky Pfau, 2018 +# Revised by Cameron Cawley, 2018 +# Revised by Cosmin Truta, 2018 +# Revised by Kyle Bentley, 2018 # This code is released under the libpng license. # For conditions of distribution and use, see the disclaimer # and license in png.h -cmake_minimum_required(VERSION 2.8.3) -cmake_policy(VERSION 2.8.3) +cmake_minimum_required(VERSION 3.1) +cmake_policy(VERSION 3.1) -# 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 C) +project(libpng C ASM) enable_testing() set(PNGLIB_MAJOR 1) set(PNGLIB_MINOR 6) -set(PNGLIB_RELEASE 23) +set(PNGLIB_RELEASE 37) set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) -# needed packages -find_package(ZLIB REQUIRED) -include_directories(${ZLIB_INCLUDE_DIR}) +include(GNUInstallDirs) -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() +# needed packages + +# Allow users to specify location of Zlib. +# Useful if zlib is being built alongside this as a sub-project. +option(PNG_BUILD_ZLIB "Custom zlib Location, else find_package is used" OFF) + +if(NOT PNG_BUILD_ZLIB) + find_package(ZLIB REQUIRED) + include_directories(${ZLIB_INCLUDE_DIR}) +endif() + +if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) + find_library(M_LIBRARY m) else() - # not needed on windows + # libm is not needed and/or not available set(M_LIBRARY "") endif() @@ -63,12 +57,145 @@ option(PNG_TESTS "Build libpng tests" ON) # Many more configuration options could be added here option(PNG_FRAMEWORK "Build OS X framework" OFF) -option(PNG_DEBUG "Build with debug output" OFF) -option(PNGARG "Disable ANSI-C prototypes" OFF) +option(PNG_DEBUG "Build with debug output" OFF) +option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON) set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names") set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings") +if(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(PNG_ARM_NEON_POSSIBLE_VALUES check on off) + set(PNG_ARM_NEON "check" CACHE STRING "Enable ARM NEON optimizations: + check: (default) use internal checking code; + off: disable the optimizations; + on: turn on unconditionally.") + set_property(CACHE PNG_ARM_NEON PROPERTY STRINGS + ${PNG_ARM_NEON_POSSIBLE_VALUES}) + list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_ARM_NEON} STREQUAL "off") + set(libpng_arm_sources + arm/arm_init.c + arm/filter_neon.S + arm/filter_neon_intrinsics.c + arm/palette_neon_intrinsics.c) + + if(${PNG_ARM_NEON} STREQUAL "on") + add_definitions(-DPNG_ARM_NEON_OPT=2) + elseif(${PNG_ARM_NEON} STREQUAL "check") + add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED) + endif() + else() + add_definitions(-DPNG_ARM_NEON_OPT=0) + endif() +endif() + +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) + set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations: + off: disable the optimizations.") + set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS + ${PNG_POWERPC_VSX_POSSIBLE_VALUES}) + list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "off") + set(libpng_powerpc_sources + powerpc/powerpc_init.c + powerpc/filter_vsx_intrinsics.c) + if(${PNG_POWERPC_VSX} STREQUAL "on") + add_definitions(-DPNG_POWERPC_VSX_OPT=2) + endif() + else() + add_definitions(-DPNG_POWERPC_VSX_OPT=0) + endif() +endif() + +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) + set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations: + off: disable the optimizations") + set_property(CACHE PNG_INTEL_SSE PROPERTY STRINGS + ${PNG_INTEL_SSE_POSSIBLE_VALUES}) + list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_INTEL_SSE} STREQUAL "off") + set(libpng_intel_sources + intel/intel_init.c + intel/filter_sse2_intrinsics.c) + if(${PNG_INTEL_SSE} STREQUAL "on") + add_definitions(-DPNG_INTEL_SSE_OPT=1) + endif() + else() + add_definitions(-DPNG_INTEL_SSE_OPT=0) + endif() +endif() + +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) + set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations: + off: disable the optimizations") + set_property(CACHE PNG_MIPS_MSA PROPERTY STRINGS + ${PNG_MIPS_MSA_POSSIBLE_VALUES}) + list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_MIPS_MSA} STREQUAL "off") + set(libpng_mips_sources + mips/mips_init.c + mips/filter_msa_intrinsics.c) + if(${PNG_MIPS_MSA} STREQUAL "on") + add_definitions(-DPNG_MIPS_MSA_OPT=2) + endif() + else() + add_definitions(-DPNG_MIPS_MSA_OPT=0) + endif() +endif() + +else(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + add_definitions(-DPNG_ARM_NEON_OPT=0) +endif() + +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + add_definitions(-DPNG_POWERPC_VSX_OPT=0) +endif() + +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + add_definitions(-DPNG_INTEL_SSE_OPT=0) +endif() + +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + add_definitions(-DPNG_MIPS_MSA_OPT=0) +endif() + +endif(PNG_HARDWARE_OPTIMIZATIONS) + # SET LIBNAME set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) @@ -124,17 +251,17 @@ function(symbol_prefix) foreach(line ${OUT}) string(REGEX MATCH "^PREFIX=" found_match "${line}") if(found_match) - STRING(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}") + 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}") + 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) + message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}") + set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE) endfunction() if(UNIX) @@ -145,7 +272,7 @@ find_program(AWK NAMES gawk awk) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -if(NOT AWK) +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) @@ -159,11 +286,11 @@ else() 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.") + if(NOT _GC_INPUT) + message(FATAL_ERROR "generate_chk: Missing INPUT argument") endif() - if (NOT _GC_OUTPUT) - message(FATAL_ERROR "Invalid arguments. generate_out requires output.") + if(NOT _GC_OUTPUT) + message(FATAL_ERROR "generate_chk: Missing OUTPUT argument") endif() add_custom_command(OUTPUT "${_GC_OUTPUT}" @@ -182,11 +309,11 @@ else() 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.") + if(NOT _GO_INPUT) + message(FATAL_ERROR "generate_out: Missing INPUT argument") endif() - if (NOT _GO_OUTPUT) - message(FATAL_ERROR "Invalid arguments. generate_out requires output.") + if(NOT _GO_OUTPUT) + message(FATAL_ERROR "generate_out: Missing OUTPUT argument") endif() add_custom_command(OUTPUT "${_GO_OUTPUT}" @@ -205,8 +332,8 @@ else() 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.") + if(NOT _GSO_OUTPUT) + message(FATAL_ERROR "generate_source: Missing OUTPUT argument") endif() add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}" @@ -307,7 +434,7 @@ else() 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 + # they are depended upon separately by multiple targets, this # confuses parallel make (it would require a separate top-level # target for each file to track the dependencies properly). add_custom_target(genfiles DEPENDS @@ -324,7 +451,7 @@ else() "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out") -endif(NOT AWK) +endif(NOT AWK OR ANDROID) # OUR SOURCES set(libpng_public_hdrs @@ -338,7 +465,7 @@ set(libpng_private_hdrs pnginfo.h pngstruct.h ) -if(AWK) +if(AWK AND NOT ANDROID) list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h") endif() set(libpng_sources @@ -359,6 +486,10 @@ set(libpng_sources pngwrite.c pngwtran.c pngwutil.c + ${libpng_arm_sources} + ${libpng_intel_sources} + ${libpng_mips_sources} + ${libpng_powerpc_sources} ) set(pngtest_sources pngtest.c @@ -384,7 +515,7 @@ set(png_fix_itxt_sources if(MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE) -endif(MSVC) +endif() if(PNG_DEBUG) add_definitions(-DPNG_DEBUG) @@ -464,7 +595,7 @@ 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") + "PNG_STATIC, PNG_SHARED, PNG_FRAMEWORK") endif() if(PNG_SHARED AND WIN32) @@ -477,11 +608,11 @@ function(png_add_test) 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.") + if(NOT _PAT_NAME) + message(FATAL_ERROR "png_add_test: Missing NAME argument") endif() - if (NOT _PAT_COMMAND) - message(FATAL_ERROR "Invalid arguments. png_add_test requires command.") + if(NOT _PAT_COMMAND) + message(FATAL_ERROR "png_add_test: Missing COMMAND argument") endif() set(TEST_OPTIONS "${_PAT_OPTIONS}") @@ -489,19 +620,11 @@ function(png_add_test) 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=$" - "-DTEST_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() + add_test(NAME "${_PAT_NAME}" + COMMAND "${CMAKE_COMMAND}" + "-DLIBPNG=$" + "-DTEST_COMMAND=$" + -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake") endfunction() if(PNG_TESTS AND PNG_SHARED) @@ -566,11 +689,11 @@ if(PNG_TESTS AND PNG_SHARED) set(TEST_PNG_VALID TRUE) if(TEST_PNG_ALPHA) - if (NOT "${alpha_type}" STREQUAL "alpha") + if(NOT "${alpha_type}" STREQUAL "alpha") set(TEST_PNG_VALID FALSE) endif() else() - if ("${alpha_type}" STREQUAL "alpha") + if("${alpha_type}" STREQUAL "alpha") set(TEST_PNG_VALID FALSE) endif() endif() @@ -634,31 +757,51 @@ if(PNG_SHARED) list(APPEND PNG_BIN_TARGETS png-fix-itxt) endif() -# Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set -IF(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) - SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "lib") -ENDIF(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) - # Set a variable with CMake code which: # Creates a symlink from src to dest (if possible) or alternatively # copies if different. -macro(CREATE_SYMLINK SRC_FILE DEST_FILE) - FILE(REMOVE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE}) - if(WIN32 AND NOT CYGWIN AND NOT MSYS) - ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${DEST_FILE} - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SRC_FILE}" ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE} - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SRC_FILE}" ${CMAKE_CURRENT_BINARY_DIR}/${DEST_FILE} - DEPENDS ${PNG_LIB_TARGETS} - ) - ADD_CUSTOM_TARGET(${DEST_FILE}_COPY ALL DEPENDS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE}) - else(WIN32 AND NOT CYGWIN AND NOT MSYS) - get_filename_component(LINK_TARGET "${SRC_FILE}" NAME) - execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) - execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${LINK_TARGET}" ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${LINK_TARGET}" ${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endif(WIN32 AND NOT CYGWIN AND NOT MSYS) -endmacro() +include(CMakeParseArguments) + +function(create_symlink DEST_FILE) + + cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN}) + + if(NOT S_TARGET AND NOT S_FILE) + message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument") + endif() + + if(S_TARGET AND S_FILE) + message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.") + endif() + + if(S_FILE) + # If we don't need to symlink something that's coming from a build target, + # we can go ahead and symlink/copy at configure time. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + execute_process( + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + else() + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endif() + + if(S_TARGET) + # We need to use generator expressions, which can be a bit tricky, so for + # simplicity make the symlink a POST_BUILD step and use the TARGET + # signature of add_custom_command. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_if_different $ $/${DEST_FILE}) + else() + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E create_symlink $ $/${DEST_FILE}) + endif() + endif() + +endfunction() # Create source generation scripts. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in @@ -668,111 +811,97 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in 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) +endif() # CREATE PKGCONFIG FILES -# we use the same files like ./configure, so we have to set its vars +# 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 +# of a UNIX look-alike. if(NOT WIN32 OR CYGWIN OR MINGW) set(prefix ${CMAKE_INSTALL_PREFIX}) set(exec_prefix ${CMAKE_INSTALL_PREFIX}) - set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) - set(includedir ${CMAKE_INSTALL_PREFIX}/include) + set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) + set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) set(LIBS "-lz -lm") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY) - CREATE_SYMLINK(${PNGLIB_NAME}.pc libpng.pc) + 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(${PNGLIB_NAME}-config libpng-config) -endif(NOT WIN32 OR CYGWIN OR MINGW) + create_symlink(libpng-config FILE ${PNGLIB_NAME}-config) +endif() # SET UP LINKS if(PNG_SHARED) set_target_properties(png PROPERTIES -# VERSION 16.${PNGLIB_RELEASE}.1.6.23 +# VERSION 16.${PNGLIB_RELEASE}.1.6.37 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 ) +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}) + EXPORT libpng + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}) if(PNG_SHARED) # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin if(CYGWIN OR MINGW) - get_target_property(BUILD_TARGET_LOCATION png LOCATION_${CMAKE_BUILD_TYPE}) - CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_IMPORT_LIBRARY_SUFFIX}) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif(CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET png) + install(FILES $/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() if(NOT WIN32) - get_target_property(BUILD_TARGET_LOCATION png LOCATION_${CMAKE_BUILD_TYPE}) - CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_SHARED_LIBRARY_SUFFIX}) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif(NOT WIN32) - endif(PNG_SHARED) + create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png) + install(FILES $/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + endif() if(PNG_STATIC) if(NOT WIN32 OR CYGWIN OR MINGW) - get_target_property(BUILD_TARGET_LOCATION png_static LOCATION_${CMAKE_BUILD_TYPE}) - CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_STATIC_LIBRARY_SUFFIX}) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif(NOT WIN32 OR CYGWIN OR MINGW) - endif() + create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static) + install(FILES $/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + endif() endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) - install(FILES ${libpng_public_hdrs} DESTINATION include) - install(FILES ${libpng_public_hdrs} DESTINATION include/${PNGLIB_NAME}) +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 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) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config DESTINATION bin) + endif() endif() -if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL ) +if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL) install(TARGETS ${PNG_BIN_TARGETS} - RUNTIME DESTINATION bin) + RUNTIME DESTINATION bin) endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) +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(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 WIN32 OR CYGWIN OR MINGW) + 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 @@ -781,12 +910,11 @@ if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config DESTINATION bin) - endif(NOT WIN32 OR CYGWIN OR MINGW) + endif() 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 ) +# Create an export file that CMake users can include() to import our targets. +if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL) install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake) endif() @@ -801,4 +929,3 @@ endif() # to create msvc import lib for mingw compiled shared lib # pexports libpng.dll > libpng.def # lib /def:libpng.def /machine:x86 - diff --git a/source/Irrlicht/libpng/INSTALL b/source/Irrlicht/libpng/INSTALL deleted file mode 100644 index 601a85b4..00000000 --- a/source/Irrlicht/libpng/INSTALL +++ /dev/null @@ -1,389 +0,0 @@ - -Installing libpng - -Contents - - I. Simple installation - II. Rebuilding the configure scripts - III. Using scripts/makefile* - IV. Using cmake - V. Directory structure - VI. Building with project files - VII. Building with makefiles -VIII. Configuring libpng for 16-bit platforms - IX. Configuring for DOS - X. Configuring for Medium Model - XI. Prepending a prefix to exported symbols - XII. Configuring for compiler xxx: -XIII. Removing unwanted object code - XIV. Changes to the build and configuration of libpng in libpng-1.5.x - XV. Setjmp/longjmp issues - XVI. Other sources of information about libpng - -I. Simple installation - -On Unix/Linux and similar systems, you can simply type - - ./configure [--prefix=/path] - make check - make install - -and ignore the rest of this document. "/path" is the path to the directory -where you want to install the libpng "lib", "include", and "bin" -subdirectories. - -If you downloaded a GIT clone, you will need to run ./autogen.sh before -running ./configure, to create "configure" and "Makefile.in" which are -not included in the GIT repository. - -Note that "configure" is only included in the "*.tar" distributions and not -in the "*.zip" or "*.7z" distributions. If you downloaded one of those -distributions, see "Building with project files" or "Building with makefiles", -below. - -II. Rebuilding the configure scripts - -If configure does not work on your system, or if you have a need to -change configure.ac or Makefile.am, and you have a reasonably -up-to-date set of tools, running ./autogen.sh in a git clone before -running ./configure may fix the problem. To be really sure that you -aren't using any of the included pre-built scripts, especially if you -are building from a tar distribution instead of a git distribution, -do this: - - ./configure --enable-maintainer-mode - make maintainer-clean - ./autogen.sh --maintainer --clean - ./autogen.sh --maintainer - ./configure [--prefix=/path] [other options] - make - make install - make check - -III. Using scripts/makefile* - -Instead, you can use one of the custom-built makefiles in the -"scripts" directory - - cp scripts/pnglibconf.h.prebuilt pnglibconf.h - cp scripts/makefile.system makefile - make test - make install - -The files that are presently available in the scripts directory -are listed and described in scripts/README.txt. - -Or you can use one of the "projects" in the "projects" directory. - -Before installing libpng, you must first install zlib, if it -is not already on your system. zlib can usually be found -wherever you got libpng; otherwise go to http://zlib.net. You can place -zlib in in the same directory as libpng or in another directory. - -If your system already has a preinstalled zlib you will still need -to have access to the zlib.h and zconf.h include files that -correspond to the version of zlib that's installed. - -If you wish to test with a particular zlib that is not first in the -standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS, -and LD_LIBRARY_PATH in your environment before running "make test" -or "make distcheck": - -ZLIBLIB=/path/to/lib export ZLIBLIB -ZLIBINC=/path/to/include export ZLIBINC -CPPFLAGS="-I$ZLIBINC" export CPPFLAGS -LDFLAGS="-L$ZLIBLIB" export LDFLAGS -LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH - -If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC -in your environment and type "make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test". - -IV. Using cmake - -If you want to use "cmake" (see www.cmake.org), type - - cmake . -DCMAKE_INSTALL_PREFIX=/path - make - make install - -As when using the simple configure method described above, "/path" points to -the installation directory where you want to put the libpng "lib", "include", -and "bin" subdirectories. - -V. Directory structure - -You can rename the directories that you downloaded (they -might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8" -or "zlib128") so that you have directories called "zlib" and "libpng". - -Your directory structure should look like this: - - .. (the parent directory) - libpng (this directory) - INSTALL (this file) - README - *.h, *.c => libpng source files - CMakeLists.txt => "cmake" script - configuration files: - configure.ac, configure, Makefile.am, Makefile.in, - autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in, - libpng-config.in, aclocal.m4, config.h.in, config.sub, - depcomp, install-sh, mkinstalldirs, test-pngtest.sh - contrib - arm-neon, conftest, examples, gregbook, libtests, pngminim, - pngminus, pngsuite, tools, visupng - projects - cbuilder5, owatcom, visualc71, vstudio, xcode - scripts - makefile.* - *.def (module definition files) - etc. - pngtest.png - etc. - zlib - README, *.h, *.c contrib, etc. - -If the line endings in the files look funny, you may wish to get the other -distribution of libpng. It is available in both tar.gz (UNIX style line -endings) and zip (DOS style line endings) formats. - -VI. Building with project files - -If you are building libpng with MSVC, you can enter the -libpng projects\visualc71 or vstudio directory and follow the instructions -in README.txt. - -Otherwise enter the zlib directory and follow the instructions in zlib/README, -then come back here and run "configure" or choose the appropriate -makefile.sys in the scripts directory. - -VII. Building with makefiles - -Copy the file (or files) that you need from the -scripts directory into this directory, for example - - MSDOS example: copy scripts\makefile.msc makefile - copy scripts\pnglibconf.h.prebuilt pnglibconf.h - UNIX example: cp scripts/makefile.std makefile - cp scripts/pnglibconf.h.prebuilt pnglibconf.h - -Read the makefile to see if you need to change any source or -target directories to match your preferences. - -Then read pnglibconf.dfa to see if you want to make any configuration -changes. - -Then just run "make" which will create the libpng library in -this directory and "make test" which will run a quick test that reads -the "pngtest.png" file and writes a "pngout.png" file that should be -identical to it. Look for "9782 zero samples" in the output of the -test. For more confidence, you can run another test by typing -"pngtest pngnow.png" and looking for "289 zero samples" in the output. -Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare -your output with the result shown in contrib/pngsuite/README. - -Most of the makefiles will allow you to run "make install" to -put the library in its final resting place (if you want to -do that, run "make install" in the zlib directory first if necessary). -Some also allow you to run "make test-installed" after you have -run "make install". - -VIII. Configuring libpng for 16-bit platforms - -You will want to look into zconf.h to tell zlib (and thus libpng) that -it cannot allocate more than 64K at a time. Even if you can, the memory -won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. - -IX. Configuring for DOS - -For DOS users who only have access to the lower 640K, you will -have to limit zlib's memory usage via a png_set_compression_mem_level() -call. See zlib.h or zconf.h in the zlib library for more information. - -X. Configuring for Medium Model - -Libpng's support for medium model has been tested on most of the popular -compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets -defined, and FAR gets defined to far in pngconf.h, and you should be -all set. Everything in the library (except for zlib's structure) is -expecting far data. You must use the typedefs with the p or pp on -the end for pointers (or at least look at them and be careful). Make -note that the rows of data are defined as png_bytepp, which is -an "unsigned char far * far *". - -XI. Prepending a prefix to exported symbols - -Starting with libpng-1.6.0, you can configure libpng (when using the -"configure" script) to prefix all exported symbols by means of the -configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any -string beginning with a letter and containing only uppercase -and lowercase letters, digits, and the underscore (i.e., a C language -identifier). This creates a set of macros in pnglibconf.h, so this is -transparent to applications; their function calls get transformed by -the macros to use the modified names. - -XII. Configuring for compiler xxx: - -All includes for libpng are in pngconf.h. If you need to add, change -or delete an include, this is the place to do it. -The includes that are not needed outside libpng are placed in pngpriv.h, -which is only used by the routines inside libpng itself. -The files in libpng proper only include pngpriv.h and png.h, which -in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h. -As of libpng-1.5.0, pngpriv.h also includes three other private header -files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material -that previously appeared in the public headers. - -XIII. Removing unwanted object code - -There are a bunch of #define's in pngconf.h that control what parts of -libpng are compiled. All the defines end in _SUPPORTED. If you are -never going to use a capability, you can change the #define to #undef -before recompiling libpng and save yourself code and data space, or -you can turn off individual capabilities with defines that begin with -PNG_NO_. - -In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. - -You can also turn all of the transforms and ancillary chunk capabilities -off en masse with compiler directives that define -PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, -or all four, along with directives to turn on any of the capabilities that -you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the -extra transformations but still leave the library fully capable of reading -and writing PNG files with all known public chunks. Use of the -PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library -that is incapable of reading or writing ancillary chunks. If you are -not using the progressive reading capability, you can turn that off -with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING -capability, which you'll still have). - -All the reading and writing specific code are in separate files, so the -linker should only grab the files it needs. However, if you want to -make sure, or if you are building a stand alone library, all the -reading files start with "pngr" and all the writing files start with "pngw". -The files that don't match either (like png.c, pngtrans.c, etc.) -are used for both reading and writing, and always need to be included. -The progressive reader is in pngpread.c - -If you are creating or distributing a dynamically linked library (a .so -or DLL file), you should not remove or disable any parts of the library, -as this will cause applications linked with different versions of the -library to fail if they call functions not available in your library. -The size of the library itself should not be an issue, because only -those sections that are actually used will be loaded into memory. - -XIV. Changes to the build and configuration of libpng in libpng-1.5.x - -Details of internal changes to the library code can be found in the CHANGES -file and in the GIT repository logs. These will be of no concern to the vast -majority of library users or builders; however, the few who configure libpng -to a non-default feature set may need to change how this is done. - -There should be no need for library builders to alter build scripts if -these use the distributed build support - configure or the makefiles - -however, users of the makefiles may care to update their build scripts -to build pnglibconf.h where the corresponding makefile does not do so. - -Building libpng with a non-default configuration has changed completely. -The old method using pngusr.h should still work correctly even though the -way pngusr.h is used in the build has been changed; however, library -builders will probably want to examine the changes to take advantage of -new capabilities and to simplify their build system. - -A. Specific changes to library configuration capabilities - -The exact mechanism used to control attributes of API functions has -changed. A single set of operating system independent macro definitions -is used and operating system specific directives are defined in -pnglibconf.h - -As part of this the mechanism used to choose procedure call standards on -those systems that allow a choice has been changed. At present this only -affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems -running on Intel processors. As before, PNGAPI is defined where required -to control the exported API functions; however, two new macros, PNGCBAPI -and PNGCAPI, are used instead for callback functions (PNGCBAPI) and -(PNGCAPI) for functions that must match a C library prototype (currently -only png_longjmp_ptr, which must match the C longjmp function.) The new -approach is documented in pngconf.h - -Despite these changes, libpng 1.5.0 only supports the native C function -calling standard on those platforms tested so far (__cdecl on Microsoft -Windows). This is because the support requirements for alternative -calling conventions seem to no longer exist. Developers who find it -necessary to set PNG_API_RULE to 1 should advise the mailing list -(png-mng-implement) of this and library builders who use Openwatcom and -therefore set PNG_API_RULE to 2 should also contact the mailing list. - -B. Changes to the configuration mechanism - -Prior to libpng-1.5.0 library builders who needed to configure libpng -had either to modify the exported pngconf.h header file to add system -specific configuration or had to write feature selection macros into -pngusr.h and cause this to be included into pngconf.h by defining -PNG_USER_CONFIG. The latter mechanism had the disadvantage that an -application built without PNG_USER_CONFIG defined would see the -unmodified, default, libpng API and thus would probably fail to link. - -These mechanisms still work in the configure build and in any makefile -build that builds pnglibconf.h, although the feature selection macros -have changed somewhat as described above. In 1.5.0, however, pngusr.h is -processed only once, at the time the exported header file pnglibconf.h is -built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored -after the build of pnglibconf.h and it is never included in an application -build. - -The formerly used alternative of adding a list of feature macros to the -CPPFLAGS setting in the build also still works; however, the macros will be -copied to pnglibconf.h and this may produce macro redefinition warnings -when the individual C files are compiled. - -All configuration now only works if pnglibconf.h is built from -scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan -(the original author of awk) maintains C source code of that awk and this -and all known later implementations (often called by subtly different -names - nawk and gawk for example) are adequate to build pnglibconf.h. -The Sun Microsystems (now Oracle) program 'awk' is an earlier version -and does not work; this may also apply to other systems that have a -functioning awk called 'nawk'. - -Configuration options are now documented in scripts/pnglibconf.dfa. This -file also includes dependency information that ensures a configuration is -consistent; that is, if a feature is switched off, dependent features are -also switched off. As a recommended alternative to using feature macros in -pngusr.h a system builder may also define equivalent options in pngusr.dfa -(or, indeed, any file) and add that to the configuration by setting -DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate -how to do this, and also illustrate a case where pngusr.h is still required. - -After you have built libpng, the definitions that were recorded in -pnglibconf.h are available to your application (pnglibconf.h is included -in png.h and gets installed alongside png.h and pngconf.h in your -$PREFIX/include directory). Do not edit pnglibconf.h after you have built -libpng, because than the settings would not accurately reflect the settings -that were used to build libpng. - -XV. Setjmp/longjmp issues - -Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp() -is known to be not thread-safe on some platforms and we don't know of -any platform where it is guaranteed to be thread-safe. Therefore, if -your application is going to be using multiple threads, you should -configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with --DPNG_NO_SETJMP on your compile line, or with - - #undef PNG_SETJMP_SUPPORTED - -in your pnglibconf.h or pngusr.h. - -Starting with libpng-1.6.0, the library included a "simplified API". -This requires setjmp/longjmp, so you must either build the library -with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED -and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined. - -XVI. Other sources of information about libpng: - -Further information can be found in the README and libpng-manual.txt -files, in the individual makefiles, in png.h, and the manual pages -libpng.3 and png.5. diff --git a/source/Irrlicht/libpng/LICENSE b/source/Irrlicht/libpng/LICENSE index e4c9ecc7..10075901 100644 --- a/source/Irrlicht/libpng/LICENSE +++ b/source/Irrlicht/libpng/LICENSE @@ -1,50 +1,82 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. +PNG Reference Library License version 2 +--------------------------------------- -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * Copyright (c) 1995-2019 The PNG Reference Library Authors. + * Copyright (c) 2018-2019 Cosmin Truta. + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * Copyright (c) 1996-1997 Andreas Dilger. + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. -If you modify libpng you may insert additional notices immediately following -this sentence. +The software is supplied "as is", without warranty of any kind, +express or implied, including, without limitation, the warranties +of merchantability, fitness for a particular purpose, title, and +non-infringement. In no event shall the Copyright owners, or +anyone distributing the software, be liable for any damages or +other liability, whether in contract, tort or otherwise, arising +from, out of, or in connection with the software, or the use or +other dealings in the software, even if advised of the possibility +of such damage. -This code is released under the libpng license. +Permission is hereby granted to use, copy, modify, and distribute +this software, or portions hereof, for any purpose, without fee, +subject to the following restrictions: -libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are -Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the product + documentation would be appreciated, but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + + +PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) +----------------------------------------------------------------------- + +libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 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 + 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. + 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 +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: +license as libpng-0.96, with the following individuals added to the +list of Contributing Authors: - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik + 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, @@ -52,14 +84,14 @@ 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 + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner -Some files in the "scripts" directory have other copyright owners +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 @@ -68,63 +100,35 @@ 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 + 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. +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. + 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. + 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. + 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 -June 9, 2016 +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. diff --git a/source/Irrlicht/libpng/README b/source/Irrlicht/libpng/README index 8f615b74..98f1bb19 100644 --- a/source/Irrlicht/libpng/README +++ b/source/Irrlicht/libpng/README @@ -1,15 +1,16 @@ -README for libpng version 1.6.23 - June 9, 2016 (shared library 16.0) -See the note about version numbers near the top of png.h +README for libpng version 1.6.37 - April 14, 2019 +================================================= +See the note about version numbers near the top of png.h. See INSTALL for instructions on how to install libpng. Libpng comes in several distribution formats. Get libpng-*.tar.gz or -libpng-*.tar.xz or if you want UNIX-style line endings in the text files, -or lpng*.7z or lpng*.zip if you want DOS-style line endings. +libpng-*.tar.xz or if you want UNIX-style line endings in the text +files, or lpng*.7z or lpng*.zip if you want DOS-style line endings. Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had +fact that it's the first release fool you. The libpng library has been +in extensive use and testing since mid-1995. By late 1997 it had finally gotten to the stage where there hadn't been significant changes to the API in some time, and people have a bad feeling about libraries with versions < 1.0. Version 1.0.0 was released in @@ -23,7 +24,7 @@ earlier versions if you are using a shared library. The type of the png_uint_32, which will affect shared-library applications that use this function. -To avoid problems with changes to the internals of png info_struct, +To avoid problems with changes to the internals of the png info_struct, new APIs have been made available in 0.95 to avoid direct application access to info_ptr. These functions are the png_set_ and png_get_ functions. These functions should be used when @@ -60,94 +61,59 @@ the library action on the detection of chunk CRC errors. It is possible to set different actions based on whether the CRC error occurred in a critical or an ancillary chunk. -The changes made to the library, and bugs fixed are based on discussions -on the PNG-implement mailing list and not on material submitted -privately to Guy, Andreas, or Glenn. They will forward any good -suggestions to the list. - -For a detailed description on using libpng, read libpng-manual.txt. For -examples of libpng in a program, see example.c and pngtest.c. For usage -information and restrictions (what little they are) on libpng, see -png.h. For a description on using zlib (the compression library used by -libpng) and zlib's restrictions, see zlib.h +For a detailed description on using libpng, read libpng-manual.txt. +For examples of libpng in a program, see example.c and pngtest.c. For +usage information and restrictions (what little they are) on libpng, +see png.h. For a description on using zlib (the compression library +used by libpng) and zlib's restrictions, see zlib.h I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own needs. +compiler specific ones, but you may have to modify one for your own +needs. You should use zlib 1.0.4 or later to run this, but it MAY work with versions as old as zlib 0.95. Even so, there are bugs in older zlib versions which can cause the output of invalid compression streams for -some images. You will definitely need zlib 1.0.4 or later if you are -taking advantage of the MS-DOS "far" structure allocation for the small -and medium memory models. You should also note that zlib is a -compression library that is useful for more things than just PNG files. -You can use zlib as a drop-in replacement for fread() and fwrite() if -you are so inclined. +some images. -zlib should be available at the same place that libpng is, or at zlib.net. +You should also note that zlib is a compression library that is useful +for more things than just PNG files. You can use zlib as a drop-in +replacement for fread() and fwrite(), if you are so inclined. + +zlib should be available at the same place that libpng is, or at +https://zlib.net. You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/documents/ +these at http://www.libpng.org/pub/png/pngdocs.html . -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it -in any of those places, e-mail me, and I'll help you find it. +This code is currently being archived at libpng.sourceforge.io in the +[DOWNLOAD] area, and at http://libpng.download/src . -I am not a lawyer, but I believe 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). - -If you have any code changes, requests, problems, etc., please e-mail -them to me. Also, I'd appreciate any make files or project files, -and any modifications you needed to make to get libpng to compile, -along with a #define variable to tell what compiler/system you are on. -If you needed to add transformations to libpng, or wish libpng would -provide the image in a different way, drop me a note (and code, if -possible), so I can consider supporting the transformation. -Finally, if you get any warning messages when compiling libpng -(note: not zlib), and they are easy to fix, I'd appreciate the -fix. Please mention "libpng" somewhere in the subject line. Thanks. - -This release was created and will be supported by myself (of course -based in a large way on Guy's and Andreas' earlier work), and the PNG +This release, based in a large way on Glenn's, Guy's and Andreas' +earlier work, was created and will be supported by myself and the PNG development group. Send comments/corrections/commendations to png-mng-implement at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net +to subscribe). -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will -read mail addressed to the png-implement list, however. - -Please do not send general questions about PNG. Send them to -png-mng-misc at lists.sf.net (subscription required; visit +Send general questions about the PNG specification to png-mng-misc +at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). If you have a question about something -in the PNG specification that is related to using libpng, send it -to me. Send me any questions that start with "I was using libpng, -and ...". If in doubt, send questions to me. I'll bounce them -to others, if necessary. - -Please do not send suggestions on how to change PNG. We have -been discussing PNG for twenty years now, and it is official and -finished. If you have suggestions for libpng, however, I'll -gladly listen. Even if your suggestion is not used immediately, -it may be used later. +subscribe). Files in this distribution: ANNOUNCE => Announcement of this version, with recent changes + AUTHORS => List of contributing authors CHANGES => Description of changes between libpng versions KNOWNBUG => List of known bugs and deficiencies LICENSE => License to use and redistribute libpng README => This file TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance + TRADEMARK => Trademark information example.c => Example code for using libpng functions libpng.3 => manual page for libpng (includes libpng-manual.txt) libpng-manual.txt => Description of libpng and its functions @@ -179,18 +145,25 @@ Files in this distribution: pngwtran.c => Write data transformations pngwutil.c => Write utility functions arm => Contains optimized code for the ARM platform + powerpc => Contains optimized code for the PowerPC platform contrib => Contributions + arm-neon => Optimized code for ARM-NEON platform + powerpc-vsx => Optimized code for POWERPC-VSX platform examples => Example programs gregbook => source code for PNG reading and writing, from Greg Roelofs' "PNG: The Definitive Guide", O'Reilly, 1999 libtests => Test programs + mips-msa => Optimized code for MIPS-MSA platform pngminim => Minimal decoder, encoder, and progressive decoder programs demonstrating use of pngusr.dfa pngminus => Simple pnm2png and png2pnm programs pngsuite => Test images + testpngs tools => Various tools visupng => Contains a MSVC workspace for VisualPng + intel => Optimized code for INTEL-SSE2 platform + mips => Optimized code for MIPS platform projects => Contains project files and workspaces for building a DLL owatcom => Contains a WATCOM project for building libpng @@ -201,15 +174,10 @@ Files in this distribution: scripts => Directory containing scripts for building libpng: (see scripts/README.txt for the list of scripts) -Good luck, and happy coding. +Good luck, and happy coding! --Glenn Randers-Pehrson (current maintainer, since 1998) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ - --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com + * Cosmin Truta (current maintainer, since 2018) + * Glenn Randers-Pehrson (former maintainer, 1998-2018) + * Andreas Eric Dilger (former maintainer, 1996-1997) + * Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc.) diff --git a/source/Irrlicht/libpng/TODO b/source/Irrlicht/libpng/TODO index fc18bba9..9b2388b5 100644 --- a/source/Irrlicht/libpng/TODO +++ b/source/Irrlicht/libpng/TODO @@ -1,29 +1,23 @@ -/* TODO - list of things to do for libpng: -Final bug fixes. -Better C++ wrapper/full C++ implementation? -Fix problem with C++ and EXTERN "C". -cHRM transformation. -Remove setjmp/longjmp usage in favor of returning error codes. -Palette creation. -Add "grayscale->palette" transformation and "palette->grayscale" detection. -Improved dithering. -Multi-lingual error and warning message support. -Complete sRGB transformation (presently it simply uses gamma=0.45455). -Make profile checking optional via a png_set_something() call. -Man pages for function calls. -Better documentation. -Better filter selection - (counting huffman bits/precompression? filter inertia? filter costs?). -Histogram creation. -Text conversion between different code pages (Latin-1 -> Mac and DOS). -Avoid building gamma tables whenever possible. -Use greater precision when changing to linear gamma for compositing against - background and doing rgb-to-gray transformation. -Investigate pre-incremented loop counters and other loop constructions. -Add interpolated method of handling interlacing. -Switch to the simpler zlib (zlib/libpng) license if legally possible. -Extend pngvalid.c to validate more of the libpng transformations. - -*/ +* Fix all defects (duh!) +* Better C++ wrapper / full C++ implementation (?) +* Fix the problems with C++ and 'extern "C"'. +* cHRM transformation. +* Palette creation. +* "grayscale->palette" transformation and "palette->grayscale" detection. +* Improved dithering. +* Multi-lingual error and warning message support. +* Complete sRGB transformation. (Currently it simply uses gamma=0.45455.) +* Man pages for function calls. +* Better documentation. +* Better filter selection + (e.g., counting huffman bits/precompression; filter inertia; filter costs). +* Histogram creation. +* Text conversion between different code pages (e.g., Latin-1 -> Mac). +* Avoid building gamma tables whenever possible. +* Greater precision in changing to linear gamma for compositing against + background, and in doing rgb-to-gray transformations. +* Investigate pre-incremented loop counters and other loop constructions. +* Interpolated method of handling interlacing. +* More validations for libpng transformations. diff --git a/source/Irrlicht/libpng/TRADEMARK b/source/Irrlicht/libpng/TRADEMARK new file mode 100644 index 00000000..747a8cf9 --- /dev/null +++ b/source/Irrlicht/libpng/TRADEMARK @@ -0,0 +1,8 @@ +TRADEMARK +========= + +The name "libpng" has not been registered by the Copyright owners +as a trademark in any jurisdiction. However, because libpng has +been distributed and maintained world-wide, continually since 1995, +the Copyright owners claim "common-law trademark protection" in any +jurisdiction where common-law trademark is recognized. diff --git a/source/Irrlicht/libpng/configure b/source/Irrlicht/libpng/configure deleted file mode 100644 index 0a32060c..00000000 --- a/source/Irrlicht/libpng/configure +++ /dev/null @@ -1,19 +0,0 @@ - -echo " - There is no \"configure\" script in this distribution (*.zip or *.7z) of - libpng-1.6.23. - - Instead, please copy the appropriate makefile for your system from the - \"scripts\" directory. Read the INSTALL file for more details. - - Update, July 2004: you can get a \"configure\" based distribution - from the libpng distribution sites. Download the file - libpng-1.6.23.tar.gz or libpng-1.6.23.tar.xz. - - If the line endings in the files look funny, which is likely to be the - case if you were trying to run \"configure\" on a Linux machine, you may - wish to get the other distribution of libpng. It is available in both - tar.gz/tar.xz (UNIX style line endings, with \"configure\") and .7z/.zip - (DOS style line endings, without \"configure\") formats. -" - diff --git a/source/Irrlicht/libpng/example.c b/source/Irrlicht/libpng/example.c index 103e8cc3..122b19d3 100644 --- a/source/Irrlicht/libpng/example.c +++ b/source/Irrlicht/libpng/example.c @@ -2,18 +2,20 @@ #if 0 /* in case someone actually tries to compile this */ /* example.c - an example of using libpng - * Last changed in libpng 1.6.15 [November 20, 2014] - * Maintained 1998-2014 Glenn Randers-Pehrson - * Maintained 1996, 1997 Andreas Dilger) - * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Maintained 2018 Cosmin Truta + * Maintained 1998-2016 Glenn Randers-Pehrson + * Maintained 1996-1997 Andreas Dilger + * Written 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * * To the extent possible under law, the authors have waived * all copyright and related or neighboring rights to this file. - * This work is published from: United States. + * This work is published from: United States, Canada. */ /* This is an example of how to use libpng to read and write PNG files. - * The file libpng-manual.txt is much more verbose then this. If you have not - * read it, do so first. This was designed to be a starting point of an + * The file libpng-manual.txt is much more verbose then this. If you have + * not read it, do so first. This was designed to be a starting point of an * implementation. This is not officially part of libpng, is hereby placed * in the public domain, and therefore does not require a copyright notice. * @@ -24,16 +26,17 @@ * see also the programs in the contrib directory. */ -/* The simple, but restricted, approach to reading a PNG file or data stream - * just requires two function calls, as in the following complete program. - * Writing a file just needs one function call, so long as the data has an +/* The simple, but restricted approach to reading a PNG file or data stream + * requires just two function calls, as in the following complete program. + * Writing a file needs just one function call, so long as the data has an * appropriate layout. * * The following code reads PNG image data from a file and writes it, in a - * potentially new format, to a new file. While this code will compile there is - * minimal (insufficient) error checking; for a more realistic version look at - * contrib/examples/pngtopng.c + * potentially new format, to a new file. While this code will compile, there + * is minimal (insufficient) error checking. For a more realistic version, + * see contrib/examples/pngtopng.c */ + #include #include #include @@ -68,28 +71,28 @@ int main(int argc, const char **argv) */ buffer = malloc(PNG_IMAGE_SIZE(image)); - /* If enough memory was available read the image in the desired format - * then write the result out to the new file. 'background' is not - * necessary when reading the image because the alpha channel is + /* If enough memory was available, read the image in the desired + * format, then write the result out to the new file. 'background' is + * not necessary when reading the image, because the alpha channel is * preserved; if it were to be removed, for example if we requested * PNG_FORMAT_RGB, then either a solid background color would have to - * be supplied or the output buffer would have to be initialized to the - * actual background of the image. + * be supplied, or the output buffer would have to be initialized to + * the actual background of the image. * * The fourth argument to png_image_finish_read is the 'row_stride' - * this is the number of components allocated for the image in each * row. It has to be at least as big as the value returned by * PNG_IMAGE_ROW_STRIDE, but if you just allocate space for the - * default, minimum, size using PNG_IMAGE_SIZE as above you can pass + * default, minimum size, using PNG_IMAGE_SIZE as above, you can pass * zero. * * The final argument is a pointer to a buffer for the colormap; - * colormaps have exactly the same format as a row of image pixels (so - * you choose what format to make the colormap by setting + * colormaps have exactly the same format as a row of image pixels + * (so you choose what format to make the colormap by setting * image.format). A colormap is only returned if * PNG_FORMAT_FLAG_COLORMAP is also set in image.format, so in this * case NULL is passed as the final argument. If you do want to force - * all images into an index/color-mapped format then you can use: + * all images into an index/color-mapped format, then you can use: * * PNG_IMAGE_COLORMAP_SIZE(image) * @@ -97,7 +100,7 @@ int main(int argc, const char **argv) */ if (buffer != NULL && png_image_finish_read(&image, NULL/*background*/, buffer, - 0/*row_stride*/, NULL/*colormap*/) != 0) + 0/*row_stride*/, NULL/*colormap*/) != 0) { /* Now write the image out to the second argument. In the write * call 'convert_to_8bit' allows 16-bit data to be squashed down to @@ -105,23 +108,21 @@ int main(int argc, const char **argv) * to the 8-bit format. */ if (png_image_write_to_file(&image, argv[2], 0/*convert_to_8bit*/, - buffer, 0/*row_stride*/, NULL/*colormap*/) != 0) + buffer, 0/*row_stride*/, NULL/*colormap*/) != 0) { /* The image has been written successfully. */ exit(0); } } - else { - /* Calling png_free_image is optional unless the simplified API was - * not run to completion. In this case if there wasn't enough - * memory for 'buffer' we didn't complete the read, so we must free - * the image: + /* Calling png_image_free is optional unless the simplified API was + * not run to completion. In this case, if there wasn't enough + * memory for 'buffer', we didn't complete the read, so we must + * free the image: */ if (buffer == NULL) - png_free_image(&image); - + png_image_free(&image); else free(buffer); } @@ -130,65 +131,67 @@ int main(int argc, const char **argv) * textual message in the 'png_image' structure: */ fprintf(stderr, "pngtopng: error: %s\n", image.message); - exit (1); + exit(1); } fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n"); - exit(1); + exit(2); } /* That's it ;-) Of course you probably want to do more with PNG files than * just converting them all to 32-bit RGBA PNG files; you can do that between * the call to png_image_finish_read and png_image_write_to_file. You can also - * ask for the image data to be presented in a number of different formats. You - * do this by simply changing the 'format' parameter set before allocating the - * buffer. + * ask for the image data to be presented in a number of different formats. + * You do this by simply changing the 'format' parameter set before allocating + * the buffer. * * The format parameter consists of five flags that define various aspects of - * the image, you can simply add these together to get the format or you can use - * one of the predefined macros from png.h (as above): + * the image. You can simply add these together to get the format, or you can + * use one of the predefined macros from png.h (as above): * - * PNG_FORMAT_FLAG_COLOR: if set the image will have three color components per - * pixel (red, green and blue), if not set the image will just have one + * PNG_FORMAT_FLAG_COLOR: if set, the image will have three color components + * per pixel (red, green and blue); if not set, the image will just have one * luminance (grayscale) component. * - * PNG_FORMAT_FLAG_ALPHA: if set each pixel in the image will have an additional - * alpha value; a linear value that describes the degree the image pixel - * covers (overwrites) the contents of the existing pixel on the display. + * PNG_FORMAT_FLAG_ALPHA: if set, each pixel in the image will have an + * additional alpha value; a linear value that describes the degree the + * image pixel covers (overwrites) the contents of the existing pixel on the + * display. * - * PNG_FORMAT_FLAG_LINEAR: if set the components of each pixel will be returned - * as a series of 16-bit linear values, if not set the components will be - * returned as a series of 8-bit values encoded according to the 'sRGB' - * standard. The 8-bit format is the normal format for images intended for - * direct display, because almost all display devices do the inverse of the - * sRGB transformation to the data they receive. The 16-bit format is more - * common for scientific data and image data that must be further processed; - * because it is linear simple math can be done on the component values. - * Regardless of the setting of this flag the alpha channel is always linear, - * although it will be 8 bits or 16 bits wide as specified by the flag. + * PNG_FORMAT_FLAG_LINEAR: if set, the components of each pixel will be + * returned as a series of 16-bit linear values; if not set, the components + * will be returned as a series of 8-bit values encoded according to the + * sRGB standard. The 8-bit format is the normal format for images intended + * for direct display, because almost all display devices do the inverse of + * the sRGB transformation to the data they receive. The 16-bit format is + * more common for scientific data and image data that must be further + * processed; because it is linear, simple math can be done on the component + * values. Regardless of the setting of this flag, the alpha channel is + * always linear, although it will be 8 bits or 16 bits wide as specified by + * the flag. * - * PNG_FORMAT_FLAG_BGR: if set the components of a color pixel will be returned - * in the order blue, then green, then red. If not set the pixel components - * are in the order red, then green, then blue. + * PNG_FORMAT_FLAG_BGR: if set, the components of a color pixel will be + * returned in the order blue, then green, then red. If not set, the pixel + * components are in the order red, then green, then blue. * - * PNG_FORMAT_FLAG_AFIRST: if set the alpha channel (if present) precedes the - * color or grayscale components. If not set the alpha channel follows the + * PNG_FORMAT_FLAG_AFIRST: if set, the alpha channel (if present) precedes the + * color or grayscale components. If not set, the alpha channel follows the * components. * * You do not have to read directly from a file. You can read from memory or, * on systems that support it, from a FILE*. This is controlled by - * the particular png_image_read_from_ function you call at the start. Likewise - * on write you can write to a FILE* if your system supports it. Check the - * macro PNG_STDIO_SUPPORTED to see if stdio support has been included in your - * libpng build. + * the particular png_image_read_from_ function you call at the start. + * Likewise, on write, you can write to a FILE* if your system supports it. + * Check the macro PNG_STDIO_SUPPORTED to see if stdio support has been + * included in your libpng build. * - * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data you may need to write it in - * the 8-bit format for display. You do this by setting the convert_to_8bit + * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data, you may need to write it + * in the 8-bit format for display. You do this by setting the convert_to_8bit * flag to 'true'. * * Don't repeatedly convert between the 8-bit and 16-bit forms. There is - * significant data loss when 16-bit data is converted to the 8-bit encoding and - * the current libpng implementation of conversion to 16-bit is also + * significant data loss when 16-bit data is converted to the 8-bit encoding, + * and the current libpng implementation of conversion to 16-bit is also * significantly lossy. The latter will be fixed in the future, but the former * is unavoidable - the 8-bit format just doesn't have enough resolution. */ @@ -199,10 +202,10 @@ int main(int argc, const char **argv) * interfaces. * * All these interfaces require that you do your own error handling - your - * program must be able to arrange for control to return to your own code any - * time libpng encounters a problem. There are several ways to do this, but the - * standard way is to use the ANSI-C (C90) interface to establish a - * return point within your own code. You must do this if you do not use the + * program must be able to arrange for control to return to your own code, any + * time libpng encounters a problem. There are several ways to do this, but + * the standard way is to use the interface to establish a return + * point within your own code. You must do this if you do not use the * simplified interface (above). * * The first step is to include the header files you need, including the libpng @@ -214,7 +217,7 @@ int main(int argc, const char **argv) /* The png_jmpbuf() macro, used in error handling, became available in * libpng version 1.0.6. If you want to be able to run your code with older * versions of libpng, you must define the macro yourself (but only if it - * is not already defined by libpng!). + * is not already defined by libpng!) */ #ifndef png_jmpbuf @@ -222,10 +225,10 @@ int main(int argc, const char **argv) #endif /* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() - * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * returns zero if the image is a PNG, and nonzero otherwise. * * The function check_if_png() shown here, but not used, returns nonzero (true) - * if the file can be opened and is a PNG, 0 (false) otherwise. + * if the file can be opened and is a PNG, and 0 (false) otherwise. * * If this call is successful, and you are going to keep the file open, * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once @@ -238,7 +241,7 @@ int main(int argc, const char **argv) * * Many applications already read the first 2 or 4 bytes from the start * of the image to determine the file type, so it would be easiest just - * to pass the bytes to png_sig_cmp() or even skip that if you know + * to pass the bytes to png_sig_cmp(), or even skip that if you know * you have a PNG file, and call png_set_sig_bytes(). */ #define PNG_BYTES_TO_CHECK 4 @@ -250,14 +253,14 @@ int check_if_png(char *file_name, FILE **fp) if ((*fp = fopen(file_name, "rb")) == NULL) return 0; - /* Read in some of the signature bytes */ + /* Read in some of the signature bytes. */ if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) return 0; /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. - Return nonzero (true) if they match */ - - return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); + * Return nonzero (true) if they match. + */ + return(!png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)); } /* Read a PNG file. You may want to return an error code if the read @@ -267,7 +270,7 @@ int check_if_png(char *file_name, FILE **fp) * some or all of the magic bytes read - see comments above). */ #ifdef open_file /* prototype 1 */ -void read_png(char *file_name) /* We need to open the file */ +void read_png(char *file_name) /* We need to open the file */ { png_structp png_ptr; png_infop info_ptr; @@ -280,7 +283,7 @@ void read_png(char *file_name) /* We need to open the file */ return (ERROR); #else no_open_file /* prototype 2 */ -void read_png(FILE *fp, int sig_read) /* File is already open */ +void read_png(FILE *fp, int sig_read) /* File is already open */ { png_structp png_ptr; png_infop info_ptr; @@ -292,10 +295,10 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application - * was compiled with a compatible version of the library. REQUIRED + * was compiled with a compatible version of the library. REQUIRED. */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); + png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { @@ -316,35 +319,33 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ - if (setjmp(png_jmpbuf(png_ptr))) { - /* Free all of the memory associated with the png_ptr and info_ptr */ + /* Free all of the memory associated with the png_ptr and info_ptr. */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); - /* If we get here, we had a problem reading the file */ + /* If we get here, we had a problem reading the file. */ return (ERROR); } - /* One of the following I/O initialization methods is REQUIRED */ + /* One of the following I/O initialization methods is REQUIRED. */ #ifdef streams /* PNG file I/O method 1 */ - /* Set up the input control if you are using standard C streams */ + /* Set up the input control if you are using standard C streams. */ png_init_io(png_ptr, fp); #else no_streams /* PNG file I/O method 2 */ /* If you are using replacement read functions, instead of calling - * png_init_io() here you would call: + * png_init_io(), you would call: */ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); - /* where user_io_ptr is a structure you want available to the callbacks */ + /* where user_io_ptr is a structure you want available to the callbacks. */ #endif no_streams /* Use only one I/O method! */ /* If we have already read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); #ifdef hilevel - /* - * If you have enough memory to read in the entire image at once, + /* If you have enough memory to read in the entire image at once, * and you need to specify only transforms that can be controlled * with one of the PNG_TRANSFORM_* bits (this presently excludes * quantizing, filling, setting background, and doing gamma @@ -354,10 +355,10 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ png_read_png(png_ptr, info_ptr, png_transforms, NULL); #else - /* OK, you're doing it the hard way, with the lower-level functions */ + /* OK, you're doing it the hard way, with the lower-level functions. */ /* The call to png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). REQUIRED + * PNG file before the first IDAT (image data chunk). REQUIRED. */ png_read_info(png_ptr, info_ptr); @@ -375,7 +376,7 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ * low byte. */ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - png_set_scale_16(png_ptr); + png_set_scale_16(png_ptr); #else png_set_strip_16(png_ptr); #endif @@ -385,20 +386,21 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ */ png_set_strip_alpha(png_ptr); - /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + /* Extract multiple pixels with bit depths of 1, 2 or 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). */ + * (not useful if you are using png_set_packing). + */ png_set_packswap(png_ptr); - /* Expand paletted colors into true RGB triplets */ + /* Expand paletted colors into true RGB triplets. */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + /* Expand grayscale images to the full 8 bits from 1, 2 or 4 bits/pixel. */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); @@ -409,47 +411,43 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ png_set_tRNS_to_alpha(png_ptr); /* Set the background color to draw transparent and alpha images over. - * It is possible to set the red, green, and blue components directly - * for paletted images instead of supplying a palette index. Note that + * It is possible to set the red, green and blue components directly + * for paletted images, instead of supplying a palette index. Note that, * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ - png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - /* Some suggestions as to how to get a screen gamma value + /* Some suggestions as to how to get a screen gamma value. * * Note that screen gamma is the display_exponent, which includes - * the CRT_exponent and any correction for viewing conditions + * the CRT_exponent and any correction for viewing conditions. */ if (/* We have a user-defined screen gamma value */) - { screen_gamma = user-defined screen_gamma; - } - /* This is one way that applications share the same screen gamma value */ + /* This is one way that applications share the same screen gamma value. */ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) - { screen_gamma = atof(gamma_str); - } /* If we don't have another value */ else { - screen_gamma = PNG_DEFAULT_sRGB; /* A good guess for a PC monitor - in a dimly lit room */ - screen_gamma = PNG_GAMMA_MAC_18 or 1.0; /* Good guesses for Mac systems */ + screen_gamma = PNG_DEFAULT_sRGB; /* A good guess for a PC monitor + in a dimly lit room */ + screen_gamma = PNG_GAMMA_MAC_18 or 1.0; /* Good guesses for Mac + systems */ } /* Tell libpng to handle the gamma conversion for you. The final call * is a good guess for PC generated images, but it should be configurable - * by the user at run time by the user. It is strongly suggested that - * your application support gamma correction. + * by the user at run time. Gamma correction support in your application + * is strongly recommended. */ int intent; @@ -466,7 +464,7 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ } #ifdef PNG_READ_QUANTIZE_SUPPORTED - /* Quantize RGB files down to 8-bit palette or reduce palettes + /* Quantize RGB files down to 8-bit palette, or reduce palettes * to the number of colors available on your screen. */ if ((color_type & PNG_COLOR_MASK_COLOR) != 0) @@ -474,29 +472,26 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ int num_palette; png_colorp palette; - /* This reduces the image to the application supplied palette */ + /* This reduces the image to the application-supplied palette. */ if (/* We have our own palette */) { - /* An array of colors to which the image should be quantized */ + /* An array of colors to which the image should be quantized. */ png_color std_color_cube[MAX_SCREEN_COLORS]; - png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, - MAX_SCREEN_COLORS, NULL, 0); + MAX_SCREEN_COLORS, NULL, 0); } - /* This reduces the image to the palette supplied in the file */ + /* This reduces the image to the palette supplied in the file. */ else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) != 0) { png_uint_16p histogram = NULL; - png_get_hIST(png_ptr, info_ptr, &histogram); - png_set_quantize(png_ptr, palette, num_palette, - max_screen_colors, histogram, 0); + max_screen_colors, histogram, 0); } } #endif /* READ_QUANTIZE */ - /* Invert monochrome files to have 0 as white and 1 as black */ + /* Invert monochrome files to have 0 as white and 1 as black. */ png_set_invert_mono(png_ptr); /* If you want to shift the pixel values from the range [0,255] or @@ -506,22 +501,21 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT) != 0) { png_color_8p sig_bit_p; - png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); png_set_shift(png_ptr, sig_bit_p); } - /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + /* Flip the RGB pixels to BGR (or RGBA to BGRA). */ if ((color_type & PNG_COLOR_MASK_COLOR) != 0) png_set_bgr(png_ptr); - /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR). */ png_set_swap_alpha(png_ptr); - /* Swap bytes of 16-bit files to least significant byte first */ + /* Swap bytes of 16-bit files to least significant byte first. */ png_set_swap(png_ptr); - /* Add filler (or alpha) byte (before/after each RGB triplet) */ + /* Add filler (or alpha) byte (before/after each RGB triplet). */ png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER); #ifdef PNG_READ_INTERLACING_SUPPORTED @@ -530,75 +524,66 @@ void read_png(FILE *fp, int sig_read) /* File is already open */ * see the png_read_row() method below: */ number_passes = png_set_interlace_handling(png_ptr); -#else +#else /* !READ_INTERLACING */ number_passes = 1; #endif /* READ_INTERLACING */ - /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (ie you selected such a transform above). + * update the palette for you (i.e. you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* Allocate the memory to hold the image using the fields of info_ptr. */ - - /* The easiest way to read the image: */ png_bytep row_pointers[height]; - - /* Clear the pointer array */ for (row = 0; row < height; row++) - row_pointers[row] = NULL; - + row_pointers[row] = NULL; /* Clear the pointer array */ for (row = 0; row < height; row++) row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, - info_ptr)); + info_ptr)); - /* Now it's time to read the image. One of these methods is REQUIRED */ + /* Now it's time to read the image. One of these methods is REQUIRED. */ #ifdef entire /* Read the entire image in one go */ png_read_image(png_ptr, row_pointers); #else no_entire /* Read the image one or more scanlines at a time */ /* The other way to read images - deal with interlacing: */ - for (pass = 0; pass < number_passes; pass++) { #ifdef single /* Read the image a single row at a time */ for (y = 0; y < height; y++) - { png_read_rows(png_ptr, &row_pointers[y], NULL, 1); - } #else no_single /* Read the image several rows at a time */ for (y = 0; y < height; y += number_of_rows) { #ifdef sparkle /* Read the image using the "sparkle" effect. */ png_read_rows(png_ptr, &row_pointers[y], NULL, - number_of_rows); + number_of_rows); #else no_sparkle /* Read the image using the "rectangle" effect */ png_read_rows(png_ptr, NULL, &row_pointers[y], - number_of_rows); + number_of_rows); #endif no_sparkle /* Use only one of these two methods */ } - /* If you want to display the image after every pass, do so here */ + /* If you want to display the image after every pass, do so here. */ #endif no_single /* Use only one of these two methods */ } #endif no_entire /* Use only one of these two methods */ - /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + /* Read rest of file, and get additional chunks in info_ptr. REQUIRED. */ png_read_end(png_ptr, info_ptr); #endif hilevel - /* At this point you have read the entire image */ + /* At this point you have read the entire image. */ - /* Clean up after the read, and free any memory allocated - REQUIRED */ + /* Clean up after the read, and free any memory allocated. REQUIRED. */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - /* Close the file */ + /* Close the file. */ fclose(fp); - /* That's it */ + /* That's it! */ return (OK); } @@ -610,34 +595,30 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that - * the library version is compatible in case we are using dynamically + * the library version is compatible, in case we are using dynamically * linked libraries. */ *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - + png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (*png_ptr == NULL) { *info_ptr = NULL; return (ERROR); } - *info_ptr = png_create_info_struct(png_ptr); - if (*info_ptr == NULL) { png_destroy_read_struct(png_ptr, info_ptr, NULL); return (ERROR); } - if (setjmp(png_jmpbuf((*png_ptr)))) { png_destroy_read_struct(png_ptr, info_ptr, NULL); return (ERROR); } - /* This one's new. You will need to provide all three - * function callbacks, even if you aren't using them all. + /* You will need to provide all three function callbacks, + * even if you aren't using all of them. * If you aren't using all functions, you can specify NULL * parameters. Even when all three functions are NULL, * you need to call png_set_progressive_read_fn(). @@ -649,29 +630,28 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) * the function png_get_progressive_ptr(png_ptr). */ png_set_progressive_read_fn(*png_ptr, (void *)stream_data, - info_callback, row_callback, end_callback); - + info_callback, row_callback, end_callback); return (OK); } int process_data(png_structp *png_ptr, png_infop *info_ptr, - png_bytep buffer, png_uint_32 length) + png_bytep buffer, png_uint_32 length) { if (setjmp(png_jmpbuf((*png_ptr)))) { - /* Free the png_ptr and info_ptr memory on error */ + /* Free the png_ptr and info_ptr memory on error. */ png_destroy_read_struct(png_ptr, info_ptr, NULL); return (ERROR); } - /* This one's new also. Simply give it chunks of data as - * they arrive from the data stream (in order, of course). + /* Give chunks of data as they arrive from the data stream + * (in order, of course). * On segmented machines, don't give it any more than 64K. * The library seems to run fine with sizes of 4K, although - * you can give it much less if necessary (I assume you can + * you can give it much less if necessary. (I assume you can * give it chunks of 1 byte, but I haven't tried with less - * than 256 bytes yet). When this function returns, you may + * than 256 bytes yet.) When this function returns, you may * want to display any rows that were generated in the row * callback, if you aren't already displaying them there. */ @@ -691,10 +671,9 @@ info_callback(png_structp png_ptr, png_infop info) } row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) + png_uint_32 row_num, int pass) { - /* - * This function is called for every row in the image. If the + /* This function is called for every row in the image. If the * image is interlaced, and you turned on the interlace handler, * this function will be called for every row in every pass. * @@ -705,25 +684,22 @@ row_callback(png_structp png_ptr, png_bytep new_row, * The new row data pointer "new_row" may be NULL, indicating there is * no new data to be replaced (in cases of interlace loading). * - * If new_row is not NULL then you need to call - * png_progressive_combine_row() to replace the corresponding row as + * If new_row is not NULL, then you need to call + * png_progressive_combine_row(), to replace the corresponding row as * shown below: */ - /* Get pointer to corresponding row in our - * PNG read buffer. - */ + /* Get pointer to corresponding row in our PNG read buffer. */ png_bytep old_row = ((png_bytep *)our_data)[row_num]; #ifdef PNG_READ_INTERLACING_SUPPORTED - /* If both rows are allocated then copy the new row + /* If both rows are allocated, then copy the new row * data to the corresponding row data. */ - if ((old_row != NULL) && (new_row != NULL)) - png_progressive_combine_row(png_ptr, old_row, new_row); + if (old_row != NULL && new_row != NULL) + png_progressive_combine_row(png_ptr, old_row, new_row); - /* - * The rows and passes are called in order, so you don't really + /* The rows and passes are called in order, so you don't really * need the row_num and pass, but I'm supplying them because it * may make your life easier. * @@ -734,7 +710,6 @@ row_callback(png_structp png_ptr, png_bytep new_row, * (it just does the memcpy for you) if it will make the code * easier. Thus, you can just do this for all cases: */ - png_progressive_combine_row(png_ptr, old_row, new_row); /* where old_row is what was displayed for previous rows. Note @@ -780,15 +755,14 @@ void write_png(char *file_name /* , ... other image information ... */) * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - + png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return (ERROR); } - /* Allocate/initialize the image information data. REQUIRED */ + /* Allocate/initialize the image information data. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { @@ -797,30 +771,30 @@ void write_png(char *file_name /* , ... other image information ... */) return (ERROR); } - /* Set error handling. REQUIRED if you aren't supplying your own + /* Set up error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { - /* If we get here, we had a problem writing the file */ + /* If we get here, we had a problem writing the file. */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); return (ERROR); } - /* One of the following I/O initialization functions is REQUIRED */ + /* One of the following I/O initialization functions is REQUIRED. */ #ifdef streams /* I/O initialization method 1 */ - /* Set up the output control if you are using standard C streams */ + /* Set up the output control if you are using standard C streams. */ png_init_io(png_ptr, fp); #else no_streams /* I/O initialization method 2 */ /* If you are using replacement write functions, instead of calling - * png_init_io() here you would call + * png_init_io(), you would call: */ png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, - user_IO_flush_function); - /* where user_io_ptr is a structure you want available to the callbacks */ + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks. */ #endif no_streams /* Only use one initialization method */ #ifdef hilevel @@ -831,30 +805,32 @@ void write_png(char *file_name /* , ... other image information ... */) png_write_png(png_ptr, info_ptr, png_transforms, NULL); #else - /* This is the hard way */ + /* This is the hard way. */ /* Set the image information here. Width and height are up to 2^31, - * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on - * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * bit_depth is one of 1, 2, 4, 8 or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST - * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. + * REQUIRED. */ - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, - PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + PNG_COLOR_TYPE_???, PNG_INTERLACE_????, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - /* Set the palette if there is one. REQUIRED for indexed-color images */ - palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH - * (sizeof (png_color))); + /* Set the palette if there is one. REQUIRED for indexed-color images. */ + palette = (png_colorp)png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))); /* ... Set palette colors ... */ png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); - /* You must not free palette here, because png_set_PLTE only makes a link to - * the palette that you malloced. Wait until you are about to destroy + /* You must not free palette here, because png_set_PLTE only makes a link + * to the palette that you allocated. Wait until you are about to destroy * the png structure. */ - /* Optional significant bit (sBIT) chunk */ + /* Optional significant bit (sBIT) chunk. */ png_color_8 sig_bit; /* If we are dealing with a grayscale image then */ @@ -870,18 +846,17 @@ void write_png(char *file_name /* , ... other image information ... */) png_set_sBIT(png_ptr, info_ptr, &sig_bit); - /* Optional gamma chunk is strongly suggested if you have any guess * as to the correct gamma of the image. */ png_set_gAMA(png_ptr, info_ptr, gamma); - /* Optionally write comments into the image */ + /* Optionally write comments into the image. */ { png_text text_ptr[3]; - char key0[]="Title"; - char text0[]="Mona Lisa"; + char key0[] = "Title"; + char text0[] = "Mona Lisa"; text_ptr[0].key = key0; text_ptr[0].text = text0; text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; @@ -889,8 +864,8 @@ void write_png(char *file_name /* , ... other image information ... */) text_ptr[0].lang = NULL; text_ptr[0].lang_key = NULL; - char key1[]="Author"; - char text1[]="Leonardo DaVinci"; + char key1[] = "Author"; + char text1[] = "Leonardo DaVinci"; text_ptr[1].key = key1; text_ptr[1].text = text1; text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; @@ -898,8 +873,8 @@ void write_png(char *file_name /* , ... other image information ... */) text_ptr[1].lang = NULL; text_ptr[1].lang_key = NULL; - char key2[]="Description"; - char text2[]=""; + char key2[] = "Description"; + char text2[] = ""; text_ptr[2].key = key2; text_ptr[2].text = text2; text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; @@ -910,14 +885,14 @@ void write_png(char *file_name /* , ... other image information ... */) png_set_text(write_ptr, write_info_ptr, text_ptr, 3); } - /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs. */ - /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored + /* Note that if sRGB is present, the gAMA and cHRM chunks must be ignored * on read and, if your application chooses to write them, they must - * be written in accordance with the sRGB profile + * be written in accordance with the sRGB profile. */ - /* Write the file header information. REQUIRED */ + /* Write the file header information. REQUIRED. */ png_write_info(png_ptr, info_ptr); /* If you want, you can write the info in two steps, in case you need to @@ -941,7 +916,7 @@ void write_png(char *file_name /* , ... other image information ... */) * all optional. Only call them if you want them. */ - /* Invert monochrome pixels */ + /* Invert monochrome pixels. */ png_set_invert_mono(png_ptr); /* Shift the pixels up to a legal bit depth and fill in @@ -949,30 +924,29 @@ void write_png(char *file_name /* , ... other image information ... */) */ png_set_shift(png_ptr, &sig_bit); - /* Pack pixels into bytes */ + /* Pack pixels into bytes. */ png_set_packing(png_ptr); - /* Swap location of alpha bytes from ARGB to RGBA */ + /* Swap location of alpha bytes from ARGB to RGBA. */ png_set_swap_alpha(png_ptr); /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. + * RGB (4 channels -> 3 channels). The second parameter is not used. */ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - /* Flip BGR pixels to RGB */ + /* Flip BGR pixels to RGB. */ png_set_bgr(png_ptr); - /* Swap bytes of 16-bit files to most significant byte first */ + /* Swap bytes of 16-bit files to most significant byte first. */ png_set_swap(png_ptr); - /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */ + /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats. */ png_set_packswap(png_ptr); - /* Turn on interlace handling if you are not using png_write_image() */ + /* Turn on interlace handling if you are not using png_write_image(). */ if (interlacing != 0) number_passes = png_set_interlace_handling(png_ptr); - else number_passes = 1; @@ -982,24 +956,28 @@ void write_png(char *file_name /* , ... other image information ... */) */ png_uint_32 k, height, width; - /* In this example, "image" is a one-dimensional array of bytes */ - png_byte image[height*width*bytes_per_pixel]; + /* In this example, "image" is a one-dimensional array of bytes. */ + /* Guard against integer overflow. */ + if (height > PNG_SIZE_MAX / (width * bytes_per_pixel)) + png_error(png_ptr, "Image data buffer would be too large"); + + png_byte image[height * width * bytes_per_pixel]; png_bytep row_pointers[height]; - if (height > PNG_UINT_32_MAX/(sizeof (png_bytep))) - png_error (png_ptr, "Image is too tall to process in memory"); + if (height > PNG_UINT_32_MAX / (sizeof (png_bytep))) + png_error(png_ptr, "Image is too tall to process in memory"); - /* Set up pointers into your "image" byte array */ + /* Set up pointers into your "image" byte array. */ for (k = 0; k < height; k++) - row_pointers[k] = image + k*width*bytes_per_pixel; + row_pointers[k] = image + k * width * bytes_per_pixel; - /* One of the following output methods is REQUIRED */ + /* One of the following output methods is REQUIRED. */ #ifdef entire /* Write out the entire image data in one call */ png_write_image(png_ptr, row_pointers); - /* The other way to write the image - deal with interlacing */ + /* The other way to write the image - deal with interlacing. */ #else no_entire /* Write out the image data by one or more scanlines */ @@ -1011,27 +989,27 @@ void write_png(char *file_name /* , ... other image information ... */) /* Write a few rows at a time. */ png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); - /* If you are only writing one row at a time, this works */ + /* If you are only writing one row at a time, this works. */ for (y = 0; y < height; y++) png_write_rows(png_ptr, &row_pointers[y], 1); } #endif no_entire /* Use only one output method */ /* You can write optional chunks like tEXt, zTXt, and tIME at the end - * as well. Shouldn't be necessary in 1.2.0 and up as all the public - * chunks are supported and you can use png_set_unknown_chunks() to + * as well. Shouldn't be necessary in 1.2.0 and up, as all the public + * chunks are supported, and you can use png_set_unknown_chunks() to * register unknown chunks into the info structure to be written out. */ - /* It is REQUIRED to call this to finish writing the rest of the file */ + /* It is REQUIRED to call this to finish writing the rest of the file. */ png_write_end(png_ptr, info_ptr); #endif hilevel - /* If you png_malloced a palette, free it here (don't free info_ptr->palette, - * as recommended in versions 1.0.5m and earlier of this example; if - * libpng mallocs info_ptr->palette, libpng will free it). If you - * allocated it with malloc() instead of png_malloc(), use free() instead - * of png_free(). + /* If you png_malloced a palette, free it here. + * (Don't free info_ptr->palette, as shown in versions 1.0.5m and earlier of + * this example; if libpng mallocs info_ptr->palette, libpng will free it). + * If you allocated it with malloc() instead of png_malloc(), use free() + * instead of png_free(). */ png_free(png_ptr, palette); palette = NULL; @@ -1042,19 +1020,20 @@ void write_png(char *file_name /* , ... other image information ... */) */ png_free(png_ptr, trans); trans = NULL; - /* Whenever you use png_free() it is a good idea to set the pointer to + + /* Whenever you use png_free(), it is a good idea to set the pointer to * NULL in case your application inadvertently tries to png_free() it - * again. When png_free() sees a NULL it returns without action, thus - * avoiding the double-free security problem. + * again. When png_free() sees a NULL it returns without action, avoiding + * the double-free problem. */ - /* Clean up after the write, and free any memory allocated */ + /* Clean up after the write, and free any allocated memory. */ png_destroy_write_struct(&png_ptr, &info_ptr); - /* Close the file */ + /* Close the file. */ fclose(fp); - /* That's it */ + /* That's it! */ return (OK); } diff --git a/source/Irrlicht/libpng/libpng-config.in b/source/Irrlicht/libpng/libpng-config.in deleted file mode 100644 index 199ad876..00000000 --- a/source/Irrlicht/libpng/libpng-config.in +++ /dev/null @@ -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 < - Copyright (c) 1998-2016 Glenn Randers-Pehrson + Copyright (c) 2018-2019 Cosmin Truta + Copyright (c) 1998-2018 Glenn Randers-Pehrson This document is released under the libpng license. For conditions of distribution and use, see the disclaimer @@ -11,9 +9,13 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.6.23 - June 9, 2016 + libpng version 1.6.36, December 2018, through 1.6.37 - April 2019 + Updated and distributed by Cosmin Truta + Copyright (c) 2018-2019 Cosmin Truta + + libpng versions 0.97, January 1998, through 1.6.35 - July 2018 Updated and distributed by Glenn Randers-Pehrson - Copyright (c) 1998-2016 Glenn Randers-Pehrson + Copyright (c) 1998-2018 Glenn Randers-Pehrson libpng 1.0 beta 6 - version 0.96 - May 28, 1997 Updated and distributed by Andreas Dilger @@ -45,7 +47,6 @@ libpng-manual.txt - A description on how to use and modify libpng XIII. Detecting libpng XIV. Source code repository XV. Coding style - XVI. Y2K Compliance in libpng I. Introduction @@ -66,17 +67,17 @@ file format in application programs. The PNG specification (second edition), November 2003, is available as a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at -. The W3C and ISO documents have identical technical content. The PNG-1.2 specification is available at -. +. It is technically equivalent to the PNG specification (second edition) but has some additional material. -The PNG-1.0 specification is available as RFC 2083 - and as a -W3C Recommendation . +The PNG-1.0 specification is available as RFC 2083 at + and as a +W3C Recommendation at . Some additional chunks are described in the special-purpose public chunks documents at @@ -101,7 +102,7 @@ majority of the needs of its users. Libpng uses zlib for its compression and decompression of PNG files. Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . +be found at the zlib home page, . The zlib compression utility is a general purpose utility that is useful for more than PNG files, and can be used without libpng. See the documentation delivered with zlib for more details. @@ -348,18 +349,18 @@ Customizing libpng. FILE *fp = fopen(file_name, "rb"); if (!fp) { - return (ERROR); + return ERROR; } if (fread(header, 1, number, fp) != number) { - return (ERROR); + return ERROR; } is_png = !png_sig_cmp(header, 0, number); if (!is_png) { - return (NOT_PNG); + return NOT_PNG; } Next, png_struct and png_info need to be allocated and initialized. In @@ -378,7 +379,7 @@ create the structure, so your application should check for that. user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; png_infop info_ptr = png_create_info_struct(png_ptr); @@ -386,7 +387,7 @@ create the structure, so your application should check for that. { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); + return ERROR; } If you want to use your own memory allocation routines, @@ -421,7 +422,7 @@ free any memory. png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); - return (ERROR); + return ERROR; } Pass (png_infopp)NULL instead of &end_info if you didn't create @@ -467,8 +468,9 @@ the default, use The values for png_set_crc_action() say how libpng is to handle CRC errors in ancillary and critical chunks, and whether to use the data contained -therein. Note that it is impossible to "discard" data in a critical -chunk. +therein. Starting with libpng-1.6.26, this also governs how an ADLER32 error +is handled while reading the IDAT chunk. Note that it is impossible to +"discard" data in a critical chunk. Choices for (int) crit_action are PNG_CRC_DEFAULT 0 error/quit @@ -485,6 +487,9 @@ Choices for (int) ancil_action are PNG_CRC_QUIET_USE 4 quiet/use data PNG_CRC_NO_CHANGE 5 use the current value +When the setting for crit_action is PNG_CRC_QUIET_USE, the CRC and ADLER32 +checksums are not only ignored, but they are not evaluated. + Setting up callback code You can set up a callback function to handle any unknown chunks in the @@ -499,7 +504,7 @@ input stream. You must supply the function png_byte name[5]; png_byte *data; - png_size_t size; + size_t size; /* Note that libpng has already taken care of the CRC handling */ @@ -508,9 +513,9 @@ input stream. You must supply the function unknown chunk structure, process it, and return one of the following: */ - return (-n); /* chunk had an error */ - return (0); /* did not recognize */ - return (n); /* success */ + return -n; /* chunk had an error */ + return 0; /* did not recognize */ + return n; /* success */ } (You can give your function another name that you like instead of @@ -559,7 +564,7 @@ non-interlaced case the row that was just handled is simply one less than the passed in row number, and pass will always be 0. For the interlaced case the same applies unless the row value is 0, in which case the row just handled was the last one from one of the preceding passes. Because interlacing may skip a -pass you cannot be sure that the preceding pass is just 'pass-1', if you really +pass you cannot be sure that the preceding pass is just 'pass-1'; if you really need to know what the last pass is record (row,pass) from the callback and use the last recorded value each time. @@ -684,8 +689,9 @@ where 0x7fffffffL means unlimited. You can retrieve this limit with chunk_cache_max = png_get_chunk_cache_max(png_ptr); Libpng imposes a limit of 8 Megabytes (8,000,000 bytes) on the amount of -memory that a compressed chunk other than IDAT can occupy, when decompressed. -You can change this limit with +memory that any chunk other than IDAT can occupy, originally or when +decompressed (prior to libpng-1.6.32 the limit was only applied to compressed +chunks after decompression). You can change this limit with png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); @@ -981,15 +987,24 @@ premultiplication. png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); -This is the default libpng handling of the alpha channel - it is not -pre-multiplied into the color components. In addition the call states +Choices for the alpha_mode are + + PNG_ALPHA_PNG 0 /* according to the PNG standard */ + PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ + PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ + PNG_ALPHA_PREMULTIPLIED 1 /* as above */ + PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ + PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_ALPHA_PNG is the default libpng handling of the alpha channel. It is not +pre-multiplied into the color components. In addition the call states that the output is for a sRGB system and causes all PNG files without gAMA chunks to be assumed to be encoded using sRGB. png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); In this case the output is assumed to be something like an sRGB conformant -display preceeded by a power-law lookup table of power 1.45. This is how +display preceded by a power-law lookup table of power 1.45. This is how early Mac systems behaved. png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -997,7 +1012,7 @@ early Mac systems behaved. This is the classic Jim Blinn approach and will work in academic environments where everything is done by the book. It has the shortcoming of assuming that input PNG data with no gamma information is linear - this -is unlikely to be correct unless the PNG files where generated locally. +is unlikely to be correct unless the PNG files were generated locally. Most of the time the output precision will be so low as to show significant banding in dark areas of the image. @@ -1041,7 +1056,7 @@ faster.) When the default gamma of PNG files doesn't match the output gamma. If you have PNG files with no gamma information png_set_alpha_mode allows -you to provide a default gamma, but it also sets the ouput gamma to the +you to provide a default gamma, but it also sets the output gamma to the matching value. If you know your PNG files have a gamma that doesn't match the output you can take advantage of the fact that png_set_alpha_mode always sets the output gamma but only sets the PNG @@ -1186,7 +1201,20 @@ row_pointers prior to calling png_read_png() with png_set_rows(png_ptr, info_ptr, &row_pointers); Alternatively you could allocate your image in one big block and define -row_pointers[i] to point into the proper places in your block. +row_pointers[i] to point into the proper places in your block, but first +be sure that your platform is able to allocate such a large buffer: + + /* Guard against integer overflow */ + if (height > PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + + png_bytep buffer=png_malloc(png_ptr,height*width*pixel_size); + + for (int i=0; i PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + Remember: Before you call png_read_update_info(), the png_get_*() functions return the values corresponding to the original PNG image. After you call png_read_update_info the values refer to the image @@ -2230,7 +2278,8 @@ is exactly the same. If you are planning on displaying the image after each pass, the "rectangle" effect is generally considered the better looking one. -If you only want the "sparkle" effect, just call png_read_rows() as +If you only want the "sparkle" effect, just call png_read_row() or +png_read_rows() as normal, with the third parameter NULL. Make sure you make pass over the image number_of_passes times, and you don't change the data in the rows between calls. You can change the locations of the data, just @@ -2239,6 +2288,8 @@ pass, and assumes the data from previous passes is still valid. png_read_rows(png_ptr, row_pointers, NULL, number_of_rows); + or + png_read_row(png_ptr, row_pointers, NULL); If you only want the first effect (the rectangles), do the same as before except pass the row buffer in the third parameter, and leave @@ -2246,6 +2297,8 @@ the second parameter NULL. png_read_rows(png_ptr, NULL, row_pointers, number_of_rows); + or + png_read_row(png_ptr, NULL, row_pointers); If you don't want libpng to handle the interlacing details, just call png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. @@ -2357,7 +2410,7 @@ separate. { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } png_read_end(png_ptr, end_info); @@ -2461,6 +2514,7 @@ your application instead of by libpng, you can use PNG_INFO_gAMA, PNG_INFO_sBIT, PNG_INFO_cHRM, PNG_INFO_PLTE, PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_eXIf, PNG_INFO_hIST, PNG_INFO_pHYs, PNG_INFO_oFFs, PNG_INFO_tIME, PNG_INFO_pCAL, PNG_INFO_sRGB, @@ -2496,7 +2550,7 @@ png_infop info_ptr; user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; info_ptr = png_create_info_struct(png_ptr); @@ -2504,14 +2558,14 @@ png_infop info_ptr; { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); + return ERROR; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } /* This one's new. You can provide functions @@ -2545,7 +2599,7 @@ png_infop info_ptr; { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } /* This one's new also. Simply give it a chunk @@ -2689,7 +2743,7 @@ custom writing functions. See the discussion under Customizing libpng. FILE *fp = fopen(file_name, "wb"); if (!fp) - return (ERROR); + return ERROR; Next, png_struct and png_info need to be allocated and initialized. As these can be both relatively large, you may not want to store these @@ -2704,14 +2758,14 @@ both "png_ptr"; you can call them anything you like, such as user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } If you want to use your own memory allocation routines, @@ -2738,7 +2792,7 @@ section below for more information on the libpng error handling. { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); - return (ERROR); + return ERROR; } ... return; @@ -3060,6 +3114,11 @@ width, height, bit_depth, and color_type must be the same in each call. single transparent color for non-paletted images (PNG_INFO_tRNS) + png_set_eXIf_1(png_ptr, info_ptr, num_exif, exif); + + exif - Exif profile (array of + png_byte) (PNG_INFO_eXIf) + png_set_hIST(png_ptr, info_ptr, hist); hist - histogram of palette (array of @@ -3721,7 +3780,7 @@ in-memory bitmap formats or to be written from the same formats. If these formats do not accommodate your needs then you can, and should, use the more sophisticated APIs above - these support a wide variety of in-memory formats and a wide variety of sophisticated transformations to those formats as well -as a wide variety of APIs to manipulate ancilliary information. +as a wide variety of APIs to manipulate ancillary information. To read a PNG file using the simplified API: @@ -3815,7 +3874,7 @@ PNG_FORMAT_FLAG_LINEAR flag below. When the simplified API needs to convert between sRGB and linear colorspaces, the actual sRGB transfer curve defined in the sRGB specification (see the -article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 approximation used elsewhere in libpng. When an alpha channel is present it is expected to denote pixel coverage @@ -3997,7 +4056,7 @@ Flags containing additional information about the image are held in the 'flags' field of png_image. PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB == 0x01 - This indicates the the RGB values of the in-memory bitmap do not + This indicates that the RGB values of the in-memory bitmap do not correspond to the red, green and blue end-points defined by sRGB. PNG_IMAGE_FLAG_FAST == 0x02 @@ -4044,7 +4103,7 @@ READ APIs The PNG header is read from the stdio FILE object. int png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) The PNG header is read from the given memory buffer. @@ -4079,7 +4138,7 @@ READ APIs When the simplified API needs to convert between sRGB and linear colorspaces, the actual sRGB transfer curve defined in the sRGB specification (see the -article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 approximation used elsewhere in libpng. WRITE APIS @@ -4197,10 +4256,10 @@ png_get_io_ptr(). For example: The replacement I/O functions must have prototypes as follows: void user_read_data(png_structp png_ptr, - png_bytep data, png_size_t length); + png_bytep data, size_t length); void user_write_data(png_structp png_ptr, - png_bytep data, png_size_t length); + png_bytep data, size_t length); void user_flush_data(png_structp png_ptr); @@ -4237,8 +4296,6 @@ functions after png_create_*_struct() has been called by calling: png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn); - png_voidp error_ptr = png_get_error_ptr(png_ptr); - If NULL is supplied for either error_fn or warning_fn, then the libpng default function will be used, calling fprintf() and/or longjmp() if a problem is encountered. The replacement error functions should have @@ -4250,6 +4307,11 @@ parameters as follows: void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg); +Then, within your user_error_fn or user_warning_fn, you can retrieve +the error_ptr if you need it, by calling + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + The motivation behind using setjmp() and longjmp() is the C++ throw and catch exception handling methods. This makes the code much easier to write, as there is no need to check every return code of every function call. @@ -4257,7 +4319,7 @@ However, there are some uncertainties about the status of local variables after a longjmp, so the user may want to be careful about doing anything after setjmp returns non-zero besides returning itself. Consult your compiler documentation for more details. For an alternative approach, you -may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net), +may wish to use the "cexcept" facility (see https://cexcept.sourceforge.io/), which is illustrated in pngvalid.c and in contrib/visupng. Beginning in libpng-1.4.0, the png_set_benign_errors() API became available. @@ -4460,7 +4522,7 @@ When PNG_DEBUG = 1, the macros are defined, but only png_debug statements having level = 0 will be printed. There aren't any such statements in this version of libpng, but if you insert some they will be printed. -VII. MNG support +VII. MNG support The MNG specification (available at http://www.libpng.org/pub/mng) allows certain extensions to PNG for PNG images that are embedded in MNG datastreams. @@ -4485,9 +4547,9 @@ in a MNG datastream. As a minimum, it must have the MNG 8-byte signature and the MHDR and MEND chunks. Libpng does not provide support for these or any other MNG chunks; your application must provide its own support for them. You may wish to consider using libmng (available at -http://www.libmng.com) instead. +https://www.libmng.com/) instead. -VIII. Changes to Libpng from version 0.88 +VIII. Changes to Libpng from version 0.88 It should be noted that versions of libpng later than 0.96 are not distributed by the original libpng author, Guy Schalnat, nor by @@ -4542,7 +4604,7 @@ application: png_uint_32 application_vn = PNG_LIBPNG_VER; -IX. Changes to Libpng from version 1.0.x to 1.2.x +IX. Changes to Libpng from version 1.0.x to 1.2.x Support for user memory management was enabled by default. To accomplish this, the functions png_create_read_struct_2(), @@ -4639,7 +4701,7 @@ which also expands tRNS to alpha was replaced with png_set_expand_gray_1_2_4_to_8() which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. -X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x +X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x Private libpng prototypes and macro definitions were moved from png.h and pngconf.h into a new pngpriv.h header file. @@ -4723,7 +4785,7 @@ behavior in case the application runs out of memory part-way through the process. We changed the prototypes of png_get_compression_buffer_size() and -png_set_compression_buffer_size() to work with png_size_t instead of +png_set_compression_buffer_size() to work with size_t instead of png_uint_32. Support for numbered error messages was removed by default, since we @@ -4749,7 +4811,7 @@ was renamed to PNG_READ_QUANTIZE_SUPPORTED. We removed the trailing '.' from the warning and error messages. -XI. Changes to Libpng from version 1.4.x to 1.5.x +XI. Changes to Libpng from version 1.4.x to 1.5.x From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. @@ -4812,7 +4874,7 @@ to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. There are changes of form in png.h, including new and changed macros to declare parts of the API. Some API functions with arguments that are pointers to data not modified within the function have been corrected to -declare these arguments with PNG_CONST. +declare these arguments with const. Much of the internal use of C macros to control the library build has also changed and some of this is visible in the exported header files, in @@ -4908,18 +4970,14 @@ PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said that it could be used to override them. Now this function will reduce or increase the limits. -Starting in libpng-1.5.10, the user limits can be set en masse with the -configuration option PNG_SAFE_LIMITS_SUPPORTED. If this option is enabled, -a set of "safe" limits is applied in pngpriv.h. These can be overridden by -application calls to png_set_user_limits(), png_set_user_chunk_cache_max(), -and/or png_set_user_malloc_max() that increase or decrease the limits. Also, -in libpng-1.5.10 the default width and height limits were increased -from 1,000,000 to 0x7fffffff (i.e., made unlimited). Therefore, the -limits are now - default safe +Starting in libpng-1.5.22, default user limits were established. These +can be overridden by application calls to png_set_user_limits(), +png_set_user_chunk_cache_max(), and/or png_set_user_malloc_max(). +The limits are now + max possible default png_user_width_max 0x7fffffff 1,000,000 png_user_height_max 0x7fffffff 1,000,000 - png_user_chunk_cache_max 0 (unlimited) 128 + png_user_chunk_cache_max 0 (unlimited) 1000 png_user_chunk_malloc_max 0 (unlimited) 8,000,000 The png_set_option() function (and the "options" member of the png struct) was @@ -5011,7 +5069,7 @@ even though the default is to use the macros - this allows applications to choose at app buildtime whether or not to use macros (previously impossible because the functions weren't in the default build.) -XII. Changes to Libpng from version 1.5.x to 1.6.x +XII. Changes to Libpng from version 1.5.x to 1.6.x A "simplified API" has been added (see documentation in png.h and a simple example in contrib/examples/pngtopng.c). The new publicly visible API @@ -5169,7 +5227,12 @@ is an error. Previously this requirement of the PNG specification was not enforced, and the palette was always limited to 256 entries. An over-length PLTE chunk found in an input PNG is silently truncated. -XIII. Detecting libpng +Starting with libpng-1.6.31, the eXIf chunk is supported. Libpng does not +attempt to decode the Exif profile; it simply returns a byte array +containing the profile to the calling application which must do its own +decoding. + +XIII. Detecting libpng The png_get_io_ptr() function has been present since libpng-0.88, has never changed, and is unaffected by conditional compilation macros. It is the @@ -5185,27 +5248,32 @@ control. The git repository was built from old libpng-x.y.z.tar.gz files going back to version 0.70. You can access the git repository (read only) at - git://git.code.sf.net/p/libpng/code + https://github.com/glennrp/libpng or + https://git.code.sf.net/p/libpng/code.git -or you can browse it with a web browser by selecting the "code" button at +or you can browse it with a web browser at - https://sourceforge.net/projects/libpng + https://github.com/glennrp/libpng or + https://sourceforge.net/p/libpng/code/ci/libpng16/tree/ -Patches can be sent to glennrp at users.sourceforge.net or to -png-mng-implement at lists.sourceforge.net or you can upload them to -the libpng bug tracker at +Patches can be sent to png-mng-implement at lists.sourceforge.net or +uploaded to the libpng bug tracker at - http://libpng.sourceforge.net + https://libpng.sourceforge.io/ + +or as a "pull request" to + + https://github.com/glennrp/libpng/pulls We also accept patches built from the tar or zip distributions, and -simple verbal discriptions of bug fixes, reported either to the +simple verbal descriptions of bug fixes, reported either to the SourceForge bug tracker, to the png-mng-implement at lists.sf.net -mailing list, or directly to glennrp. +mailing list, as github issues. XV. Coding style Our coding style is similar to the "Allman" style -(See http://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly +(See https://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly braces on separate lines: if (condition) @@ -5221,7 +5289,7 @@ braces on separate lines: The braces can be omitted from simple one-line actions: if (condition) - return (0); + return 0; We use 3-space indentation, except for continued statements which are usually indented the same as the first line of the statement @@ -5306,7 +5374,7 @@ Prior to libpng-1.6.0 we used a "png_sizeof()" macro, formatted as though it were a function. Control keywords if, for, while, and switch are always followed by a space -to distinguish them from function calls, which have no trailing space. +to distinguish them from function calls, which have no trailing space. We put a space after each comma and after each semicolon in "for" statements, and we put spaces before and after each @@ -5330,66 +5398,12 @@ with an even number of lower-case hex digits, and to make them unsigned We prefer to use underscores rather than camelCase in names, except for a few type names that we inherit from zlib.h. -We prefer "if (something != 0)" and "if (something == 0)" -over "if (something)" and if "(!something)", respectively. +We prefer "if (something != 0)" and "if (something == 0)" over +"if (something)" and if "(!something)", respectively, and for pointers +we prefer "if (some_pointer != NULL)" or "if (some_pointer == NULL)". We do not use the TAB character for indentation in the C sources. Lines do not exceed 80 characters. Other rules can be inferred by inspecting the libpng source. - -XVI. Y2K Compliance in libpng - -Since the PNG Development group is an ad-hoc body, we can't make -an official declaration. - -This is your unofficial assurance that libpng from version 0.71 and -upward through 1.6.23 are Y2K compliant. It is my belief that earlier -versions were also Y2K compliant. - -Libpng only has two year fields. One is a 2-byte unsigned integer -that will hold years up to 65535. The other, which is deprecated, -holds the date in text format, and will hold years up to 9999. - -The integer is - "png_uint_16 year" in png_time_struct. - -The string is - "char time_buffer[29]" in png_struct. This is no longer used -in libpng-1.6.x and will be removed from libpng-1.7.0. - -There are seven time-related functions: - - png_convert_to_rfc_1123_buffer() in png.c - (formerly png_convert_to_rfc_1152() in error, and - also formerly png_convert_to_rfc_1123()) - png_convert_from_struct_tm() in pngwrite.c, called - in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - -All appear to handle dates properly in a Y2K environment. The -png_convert_from_time_t() function calls gmtime() to convert from system -clock time, which returns (year - 1900), which we properly convert to -the full 4-digit year. There is a possibility that applications using -libpng are not passing 4-digit years into the png_convert_to_rfc_1123() -function, or that they are incorrectly passing only a 2-digit year -instead of "year - 1900" into the png_convert_from_struct_tm() function, -but this is not under our control. The libpng documentation has always -stated that it works with 4-digit years, and the APIs have been -documented as such. - -The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned -integer to hold the year, and can hold years as large as 65535. - -zlib, upon which libpng depends, is also Y2K compliant. It contains -no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group diff --git a/source/Irrlicht/libpng/libpng.3 b/source/Irrlicht/libpng/libpng.3 index 9f5f2db2..aabb160b 100644 --- a/source/Irrlicht/libpng/libpng.3 +++ b/source/Irrlicht/libpng/libpng.3 @@ -1,11 +1,11 @@ -.TH LIBPNG 3 "June 9, 2016" +.TH LIBPNG 3 "April 14, 2019" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 -.SH SYNOPSIS -\fB -#include \fP +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.37 -\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP +.SH SYNOPSIS +\fB#include \fP + +\fBpng_uint_32 png_access_version_number (void);\fP \fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP @@ -35,7 +35,7 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBpng_structp png_create_write_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP -\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask)\fP\fB);\fP +\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask\fP\fB);\fP \fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP @@ -97,6 +97,10 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP +\fBpng_uint_32 png_get_eXIf (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fI*exif\fP\fB);\fP + +\fBpng_uint_32 png_get_eXIf_1 (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unit_32 \fP\fI*num_exif\fP\fB, png_bytep \fI*exif\fP\fB);\fP + \fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP \fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP @@ -221,7 +225,7 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBint png_image_begin_read_from_stdio (png_imagep \fP\fIimage\fP\fB, FILE* \fIfile\fP\fB);\fP -\fBint, png_image_begin_read_from_memory (png_imagep \fP\fIimage\fP\fB, png_const_voidp \fP\fImemory\fP\fB, png_size_t \fIsize\fP\fB);\fP +\fBint, png_image_begin_read_from_memory (png_imagep \fP\fIimage\fP\fB, png_const_voidp \fP\fImemory\fP\fB, size_t \fIsize\fP\fB);\fP \fBint png_image_finish_read (png_imagep \fP\fIimage\fP\fB, png_colorp \fP\fIbackground\fP\fB, void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP @@ -229,11 +233,11 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBint png_image_write_to_file (png_imagep \fP\fIimage\fP\fB, const char \fP\fI*file\fP\fB, int \fP\fIconvert_to_8bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP -\fBint png_image_write_to_memory (png_imagep \fP\fIimage\fP\fB, void \fP\fI*memory\fP\fB, png_alloc_size_t * PNG_RESTRICT \fP\fImemory_bytes\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, const void \fI*colormap)\fP\fB);\fP +\fBint png_image_write_to_memory (png_imagep \fP\fIimage\fP\fB, void \fP\fI*memory\fP\fB, png_alloc_size_t * PNG_RESTRICT \fP\fImemory_bytes\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, const void \fI*colormap\fP\fB);\fP -\fBint png_image_write_to_stdio (png_imagep \fP\fIimage\fP\fB, FILE \fP\fI*file\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap)\fP\fB);\fP +\fBint png_image_write_to_stdio (png_imagep \fP\fIimage\fP\fB, FILE \fP\fI*file\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP -\fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP +\fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, size_t \fIpng_info_struct_size\fP\fB);\fP \fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP @@ -247,11 +251,11 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_permitted\fP\fB);\fP -\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, size_t \fIbuffer_size\fP\fB);\fP -\fBpng_size_t png_process_data_pause \fP\fI(png_structp\fP\fB, int \fIsave\fP\fB);\fP +\fBsize_t png_process_data_pause (png_structp \fP\fIpng_ptr\fP\fB, int \fIsave\fP\fB);\fP -\fBpng_uint_32 png_process_data_skip \fI(png_structp\fP\fB);\fP +\fBpng_uint_32 png_process_data_skip (png_structp \fP\fIpng_ptr\fP\fB);\fP \fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP @@ -293,7 +297,7 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP -\fBvoid png_set_check_for_invalid_index(png_structrp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP +\fBvoid png_set_check_for_invalid_index (png_structrp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP \fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP @@ -347,6 +351,10 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP +\fBvoid png_set_eXIf (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fIexif\fP\fB);\fP + +\fBvoid png_set_eXIf_1 (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fInum_exif\fP\fB, png_bytep \fIexif\fP\fB);\fP + \fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP \fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP @@ -445,7 +453,7 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBvoid png_set_text_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP -\fBvoid \fP\fIpng_set_text_compression_method\fP\fB, (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod)\fP\fB);\fP +\fBvoid png_set_text_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP \fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP @@ -467,15 +475,15 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 \fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP -\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, size_t \fP\fIstart\fP\fB, size_t \fInum_to_check\fP\fB);\fP \fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP \fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP -\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, size_t \fIlength\fP\fB);\fP -\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, size_t \fIlength\fP\fB);\fP \fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP @@ -507,13 +515,12 @@ the Portable Network Graphics (PNG) format image files. It uses the .IR zlib(3) compression library. Following is a copy of the libpng-manual.txt file that accompanies libpng. + .SH LIBPNG.TXT libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.6.23 - June 9, 2016 - Updated and distributed by Glenn Randers-Pehrson - - Copyright (c) 1998-2016 Glenn Randers-Pehrson + Copyright (c) 2018-2019 Cosmin Truta + Copyright (c) 1998-2018 Glenn Randers-Pehrson This document is released under the libpng license. For conditions of distribution and use, see the disclaimer @@ -521,9 +528,13 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.6.23 - June 9, 2016 + libpng version 1.6.36, December 2018, through 1.6.37 - April 2019 + Updated and distributed by Cosmin Truta + Copyright (c) 2018-2019 Cosmin Truta + + libpng versions 0.97, January 1998, through 1.6.35 - July 2018 Updated and distributed by Glenn Randers-Pehrson - Copyright (c) 1998-2016 Glenn Randers-Pehrson + Copyright (c) 1998-2018 Glenn Randers-Pehrson libpng 1.0 beta 6 - version 0.96 - May 28, 1997 Updated and distributed by Andreas Dilger @@ -555,7 +566,6 @@ libpng-manual.txt - A description on how to use and modify libpng XIII. Detecting libpng XIV. Source code repository XV. Coding style - XVI. Y2K Compliance in libpng .SH I. Introduction @@ -576,17 +586,17 @@ file format in application programs. The PNG specification (second edition), November 2003, is available as a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at -. The W3C and ISO documents have identical technical content. The PNG-1.2 specification is available at -. +. It is technically equivalent to the PNG specification (second edition) but has some additional material. -The PNG-1.0 specification is available as RFC 2083 - and as a -W3C Recommendation . +The PNG-1.0 specification is available as RFC 2083 at + and as a +W3C Recommendation at . Some additional chunks are described in the special-purpose public chunks documents at @@ -611,7 +621,7 @@ majority of the needs of its users. Libpng uses zlib for its compression and decompression of PNG files. Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . +be found at the zlib home page, . The zlib compression utility is a general purpose utility that is useful for more than PNG files, and can be used without libpng. See the documentation delivered with zlib for more details. @@ -858,18 +868,18 @@ Customizing libpng. FILE *fp = fopen(file_name, "rb"); if (!fp) { - return (ERROR); + return ERROR; } if (fread(header, 1, number, fp) != number) { - return (ERROR); + return ERROR; } is_png = !png_sig_cmp(header, 0, number); if (!is_png) { - return (NOT_PNG); + return NOT_PNG; } Next, png_struct and png_info need to be allocated and initialized. In @@ -888,7 +898,7 @@ create the structure, so your application should check for that. user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; png_infop info_ptr = png_create_info_struct(png_ptr); @@ -896,7 +906,7 @@ create the structure, so your application should check for that. { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); + return ERROR; } If you want to use your own memory allocation routines, @@ -931,7 +941,7 @@ free any memory. png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); - return (ERROR); + return ERROR; } Pass (png_infopp)NULL instead of &end_info if you didn't create @@ -977,8 +987,9 @@ the default, use The values for png_set_crc_action() say how libpng is to handle CRC errors in ancillary and critical chunks, and whether to use the data contained -therein. Note that it is impossible to "discard" data in a critical -chunk. +therein. Starting with libpng-1.6.26, this also governs how an ADLER32 error +is handled while reading the IDAT chunk. Note that it is impossible to +"discard" data in a critical chunk. Choices for (int) crit_action are PNG_CRC_DEFAULT 0 error/quit @@ -995,6 +1006,9 @@ Choices for (int) ancil_action are PNG_CRC_QUIET_USE 4 quiet/use data PNG_CRC_NO_CHANGE 5 use the current value +When the setting for crit_action is PNG_CRC_QUIET_USE, the CRC and ADLER32 +checksums are not only ignored, but they are not evaluated. + .SS Setting up callback code You can set up a callback function to handle any unknown chunks in the @@ -1009,7 +1023,7 @@ input stream. You must supply the function png_byte name[5]; png_byte *data; - png_size_t size; + size_t size; /* Note that libpng has already taken care of the CRC handling */ @@ -1018,9 +1032,9 @@ input stream. You must supply the function unknown chunk structure, process it, and return one of the following: */ - return (\-n); /* chunk had an error */ - return (0); /* did not recognize */ - return (n); /* success */ + return \-n; /* chunk had an error */ + return 0; /* did not recognize */ + return n; /* success */ } (You can give your function another name that you like instead of @@ -1069,7 +1083,7 @@ non-interlaced case the row that was just handled is simply one less than the passed in row number, and pass will always be 0. For the interlaced case the same applies unless the row value is 0, in which case the row just handled was the last one from one of the preceding passes. Because interlacing may skip a -pass you cannot be sure that the preceding pass is just 'pass\-1', if you really +pass you cannot be sure that the preceding pass is just 'pass\-1'; if you really need to know what the last pass is record (row,pass) from the callback and use the last recorded value each time. @@ -1194,8 +1208,9 @@ where 0x7fffffffL means unlimited. You can retrieve this limit with chunk_cache_max = png_get_chunk_cache_max(png_ptr); Libpng imposes a limit of 8 Megabytes (8,000,000 bytes) on the amount of -memory that a compressed chunk other than IDAT can occupy, when decompressed. -You can change this limit with +memory that any chunk other than IDAT can occupy, originally or when +decompressed (prior to libpng-1.6.32 the limit was only applied to compressed +chunks after decompression). You can change this limit with png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); @@ -1491,15 +1506,24 @@ premultiplication. png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); -This is the default libpng handling of the alpha channel - it is not -pre-multiplied into the color components. In addition the call states +Choices for the alpha_mode are + + PNG_ALPHA_PNG 0 /* according to the PNG standard */ + PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ + PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ + PNG_ALPHA_PREMULTIPLIED 1 /* as above */ + PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ + PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_ALPHA_PNG is the default libpng handling of the alpha channel. It is not +pre-multiplied into the color components. In addition the call states that the output is for a sRGB system and causes all PNG files without gAMA chunks to be assumed to be encoded using sRGB. png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); In this case the output is assumed to be something like an sRGB conformant -display preceeded by a power-law lookup table of power 1.45. This is how +display preceded by a power-law lookup table of power 1.45. This is how early Mac systems behaved. png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1507,7 +1531,7 @@ early Mac systems behaved. This is the classic Jim Blinn approach and will work in academic environments where everything is done by the book. It has the shortcoming of assuming that input PNG data with no gamma information is linear - this -is unlikely to be correct unless the PNG files where generated locally. +is unlikely to be correct unless the PNG files were generated locally. Most of the time the output precision will be so low as to show significant banding in dark areas of the image. @@ -1551,7 +1575,7 @@ faster.) When the default gamma of PNG files doesn't match the output gamma. If you have PNG files with no gamma information png_set_alpha_mode allows -you to provide a default gamma, but it also sets the ouput gamma to the +you to provide a default gamma, but it also sets the output gamma to the matching value. If you know your PNG files have a gamma that doesn't match the output you can take advantage of the fact that png_set_alpha_mode always sets the output gamma but only sets the PNG @@ -1696,7 +1720,20 @@ row_pointers prior to calling png_read_png() with png_set_rows(png_ptr, info_ptr, &row_pointers); Alternatively you could allocate your image in one big block and define -row_pointers[i] to point into the proper places in your block. +row_pointers[i] to point into the proper places in your block, but first +be sure that your platform is able to allocate such a large buffer: + + /* Guard against integer overflow */ + if (height > PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + + png_bytep buffer=png_malloc(png_ptr,height*width*pixel_size); + + for (int i=0; i PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + Remember: Before you call png_read_update_info(), the png_get_*() functions return the values corresponding to the original PNG image. After you call png_read_update_info the values refer to the image @@ -2740,7 +2797,8 @@ is exactly the same. If you are planning on displaying the image after each pass, the "rectangle" effect is generally considered the better looking one. -If you only want the "sparkle" effect, just call png_read_rows() as +If you only want the "sparkle" effect, just call png_read_row() or +png_read_rows() as normal, with the third parameter NULL. Make sure you make pass over the image number_of_passes times, and you don't change the data in the rows between calls. You can change the locations of the data, just @@ -2749,6 +2807,8 @@ pass, and assumes the data from previous passes is still valid. png_read_rows(png_ptr, row_pointers, NULL, number_of_rows); + or + png_read_row(png_ptr, row_pointers, NULL); If you only want the first effect (the rectangles), do the same as before except pass the row buffer in the third parameter, and leave @@ -2756,6 +2816,8 @@ the second parameter NULL. png_read_rows(png_ptr, NULL, row_pointers, number_of_rows); + or + png_read_row(png_ptr, NULL, row_pointers); If you don't want libpng to handle the interlacing details, just call png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. @@ -2867,7 +2929,7 @@ separate. { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } png_read_end(png_ptr, end_info); @@ -2971,6 +3033,7 @@ your application instead of by libpng, you can use PNG_INFO_gAMA, PNG_INFO_sBIT, PNG_INFO_cHRM, PNG_INFO_PLTE, PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_eXIf, PNG_INFO_hIST, PNG_INFO_pHYs, PNG_INFO_oFFs, PNG_INFO_tIME, PNG_INFO_pCAL, PNG_INFO_sRGB, @@ -3006,7 +3069,7 @@ png_infop info_ptr; user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; info_ptr = png_create_info_struct(png_ptr); @@ -3014,14 +3077,14 @@ png_infop info_ptr; { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); + return ERROR; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } /* This one's new. You can provide functions @@ -3055,7 +3118,7 @@ png_infop info_ptr; { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } /* This one's new also. Simply give it a chunk @@ -3199,7 +3262,7 @@ custom writing functions. See the discussion under Customizing libpng. FILE *fp = fopen(file_name, "wb"); if (!fp) - return (ERROR); + return ERROR; Next, png_struct and png_info need to be allocated and initialized. As these can be both relatively large, you may not want to store these @@ -3214,14 +3277,14 @@ both "png_ptr"; you can call them anything you like, such as user_error_fn, user_warning_fn); if (!png_ptr) - return (ERROR); + return ERROR; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return (ERROR); + return ERROR; } If you want to use your own memory allocation routines, @@ -3248,7 +3311,7 @@ section below for more information on the libpng error handling. { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); - return (ERROR); + return ERROR; } ... return; @@ -3570,6 +3633,11 @@ width, height, bit_depth, and color_type must be the same in each call. single transparent color for non-paletted images (PNG_INFO_tRNS) + png_set_eXIf_1(png_ptr, info_ptr, num_exif, exif); + + exif - Exif profile (array of + png_byte) (PNG_INFO_eXIf) + png_set_hIST(png_ptr, info_ptr, hist); hist - histogram of palette (array of @@ -4231,7 +4299,7 @@ in-memory bitmap formats or to be written from the same formats. If these formats do not accommodate your needs then you can, and should, use the more sophisticated APIs above - these support a wide variety of in-memory formats and a wide variety of sophisticated transformations to those formats as well -as a wide variety of APIs to manipulate ancilliary information. +as a wide variety of APIs to manipulate ancillary information. To read a PNG file using the simplified API: @@ -4325,7 +4393,7 @@ PNG_FORMAT_FLAG_LINEAR flag below. When the simplified API needs to convert between sRGB and linear colorspaces, the actual sRGB transfer curve defined in the sRGB specification (see the -article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 approximation used elsewhere in libpng. When an alpha channel is present it is expected to denote pixel coverage @@ -4507,7 +4575,7 @@ Flags containing additional information about the image are held in the 'flags' field of png_image. PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB == 0x01 - This indicates the the RGB values of the in-memory bitmap do not + This indicates that the RGB values of the in-memory bitmap do not correspond to the red, green and blue end-points defined by sRGB. PNG_IMAGE_FLAG_FAST == 0x02 @@ -4554,7 +4622,7 @@ READ APIs The PNG header is read from the stdio FILE object. int png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) The PNG header is read from the given memory buffer. @@ -4589,7 +4657,7 @@ READ APIs When the simplified API needs to convert between sRGB and linear colorspaces, the actual sRGB transfer curve defined in the sRGB specification (see the -article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 approximation used elsewhere in libpng. WRITE APIS @@ -4707,10 +4775,10 @@ png_get_io_ptr(). For example: The replacement I/O functions must have prototypes as follows: void user_read_data(png_structp png_ptr, - png_bytep data, png_size_t length); + png_bytep data, size_t length); void user_write_data(png_structp png_ptr, - png_bytep data, png_size_t length); + png_bytep data, size_t length); void user_flush_data(png_structp png_ptr); @@ -4747,8 +4815,6 @@ functions after png_create_*_struct() has been called by calling: png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn); - png_voidp error_ptr = png_get_error_ptr(png_ptr); - If NULL is supplied for either error_fn or warning_fn, then the libpng default function will be used, calling fprintf() and/or longjmp() if a problem is encountered. The replacement error functions should have @@ -4760,6 +4826,11 @@ parameters as follows: void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg); +Then, within your user_error_fn or user_warning_fn, you can retrieve +the error_ptr if you need it, by calling + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + The motivation behind using setjmp() and longjmp() is the C++ throw and catch exception handling methods. This makes the code much easier to write, as there is no need to check every return code of every function call. @@ -4767,7 +4838,7 @@ However, there are some uncertainties about the status of local variables after a longjmp, so the user may want to be careful about doing anything after setjmp returns non-zero besides returning itself. Consult your compiler documentation for more details. For an alternative approach, you -may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net), +may wish to use the "cexcept" facility (see https://cexcept.sourceforge.io/), which is illustrated in pngvalid.c and in contrib/visupng. Beginning in libpng-1.4.0, the png_set_benign_errors() API became available. @@ -4970,7 +5041,7 @@ When PNG_DEBUG = 1, the macros are defined, but only png_debug statements having level = 0 will be printed. There aren't any such statements in this version of libpng, but if you insert some they will be printed. -.SH VII. MNG support +.SH VII. MNG support The MNG specification (available at http://www.libpng.org/pub/mng) allows certain extensions to PNG for PNG images that are embedded in MNG datastreams. @@ -4995,9 +5066,9 @@ in a MNG datastream. As a minimum, it must have the MNG 8-byte signature and the MHDR and MEND chunks. Libpng does not provide support for these or any other MNG chunks; your application must provide its own support for them. You may wish to consider using libmng (available at -http://www.libmng.com) instead. +https://www.libmng.com/) instead. -.SH VIII. Changes to Libpng from version 0.88 +.SH VIII. Changes to Libpng from version 0.88 It should be noted that versions of libpng later than 0.96 are not distributed by the original libpng author, Guy Schalnat, nor by @@ -5052,7 +5123,7 @@ application: png_uint_32 application_vn = PNG_LIBPNG_VER; -.SH IX. Changes to Libpng from version 1.0.x to 1.2.x +.SH IX. Changes to Libpng from version 1.0.x to 1.2.x Support for user memory management was enabled by default. To accomplish this, the functions png_create_read_struct_2(), @@ -5149,7 +5220,7 @@ which also expands tRNS to alpha was replaced with png_set_expand_gray_1_2_4_to_8() which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. -.SH X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x +.SH X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x Private libpng prototypes and macro definitions were moved from png.h and pngconf.h into a new pngpriv.h header file. @@ -5233,7 +5304,7 @@ behavior in case the application runs out of memory part-way through the process. We changed the prototypes of png_get_compression_buffer_size() and -png_set_compression_buffer_size() to work with png_size_t instead of +png_set_compression_buffer_size() to work with size_t instead of png_uint_32. Support for numbered error messages was removed by default, since we @@ -5259,7 +5330,7 @@ was renamed to PNG_READ_QUANTIZE_SUPPORTED. We removed the trailing '.' from the warning and error messages. -.SH XI. Changes to Libpng from version 1.4.x to 1.5.x +.SH XI. Changes to Libpng from version 1.4.x to 1.5.x From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. @@ -5322,7 +5393,7 @@ to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. There are changes of form in png.h, including new and changed macros to declare parts of the API. Some API functions with arguments that are pointers to data not modified within the function have been corrected to -declare these arguments with PNG_CONST. +declare these arguments with const. Much of the internal use of C macros to control the library build has also changed and some of this is visible in the exported header files, in @@ -5418,18 +5489,14 @@ PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said that it could be used to override them. Now this function will reduce or increase the limits. -Starting in libpng-1.5.10, the user limits can be set en masse with the -configuration option PNG_SAFE_LIMITS_SUPPORTED. If this option is enabled, -a set of "safe" limits is applied in pngpriv.h. These can be overridden by -application calls to png_set_user_limits(), png_set_user_chunk_cache_max(), -and/or png_set_user_malloc_max() that increase or decrease the limits. Also, -in libpng-1.5.10 the default width and height limits were increased -from 1,000,000 to 0x7fffffff (i.e., made unlimited). Therefore, the -limits are now - default safe +Starting in libpng-1.5.22, default user limits were established. These +can be overridden by application calls to png_set_user_limits(), +png_set_user_chunk_cache_max(), and/or png_set_user_malloc_max(). +The limits are now + max possible default png_user_width_max 0x7fffffff 1,000,000 png_user_height_max 0x7fffffff 1,000,000 - png_user_chunk_cache_max 0 (unlimited) 128 + png_user_chunk_cache_max 0 (unlimited) 1000 png_user_chunk_malloc_max 0 (unlimited) 8,000,000 The png_set_option() function (and the "options" member of the png struct) was @@ -5521,7 +5588,7 @@ even though the default is to use the macros - this allows applications to choose at app buildtime whether or not to use macros (previously impossible because the functions weren't in the default build.) -.SH XII. Changes to Libpng from version 1.5.x to 1.6.x +.SH XII. Changes to Libpng from version 1.5.x to 1.6.x A "simplified API" has been added (see documentation in png.h and a simple example in contrib/examples/pngtopng.c). The new publicly visible API @@ -5679,7 +5746,12 @@ is an error. Previously this requirement of the PNG specification was not enforced, and the palette was always limited to 256 entries. An over-length PLTE chunk found in an input PNG is silently truncated. -.SH XIII. Detecting libpng +Starting with libpng-1.6.31, the eXIf chunk is supported. Libpng does not +attempt to decode the Exif profile; it simply returns a byte array +containing the profile to the calling application which must do its own +decoding. + +.SH XIII. Detecting libpng The png_get_io_ptr() function has been present since libpng-0.88, has never changed, and is unaffected by conditional compilation macros. It is the @@ -5695,27 +5767,32 @@ control. The git repository was built from old libpng-x.y.z.tar.gz files going back to version 0.70. You can access the git repository (read only) at - git://git.code.sf.net/p/libpng/code + https://github.com/glennrp/libpng or + https://git.code.sf.net/p/libpng/code.git -or you can browse it with a web browser by selecting the "code" button at +or you can browse it with a web browser at - https://sourceforge.net/projects/libpng + https://github.com/glennrp/libpng or + https://sourceforge.net/p/libpng/code/ci/libpng16/tree/ -Patches can be sent to glennrp at users.sourceforge.net or to -png-mng-implement at lists.sourceforge.net or you can upload them to -the libpng bug tracker at +Patches can be sent to png-mng-implement at lists.sourceforge.net or +uploaded to the libpng bug tracker at - http://libpng.sourceforge.net + https://libpng.sourceforge.io/ + +or as a "pull request" to + + https://github.com/glennrp/libpng/pulls We also accept patches built from the tar or zip distributions, and -simple verbal discriptions of bug fixes, reported either to the +simple verbal descriptions of bug fixes, reported either to the SourceForge bug tracker, to the png-mng-implement at lists.sf.net -mailing list, or directly to glennrp. +mailing list, as github issues. .SH XV. Coding style Our coding style is similar to the "Allman" style -(See http://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly +(See https://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly braces on separate lines: if (condition) @@ -5731,7 +5808,7 @@ braces on separate lines: The braces can be omitted from simple one-line actions: if (condition) - return (0); + return 0; We use 3-space indentation, except for continued statements which are usually indented the same as the first line of the statement @@ -5816,7 +5893,7 @@ Prior to libpng-1.6.0 we used a "png_sizeof()" macro, formatted as though it were a function. Control keywords if, for, while, and switch are always followed by a space -to distinguish them from function calls, which have no trailing space. +to distinguish them from function calls, which have no trailing space. We put a space after each comma and after each semicolon in "for" statements, and we put spaces before and after each @@ -5840,8 +5917,9 @@ with an even number of lower-case hex digits, and to make them unsigned We prefer to use underscores rather than camelCase in names, except for a few type names that we inherit from zlib.h. -We prefer "if (something != 0)" and "if (something == 0)" -over "if (something)" and if "(!something)", respectively. +We prefer "if (something != 0)" and "if (something == 0)" over +"if (something)" and if "(!something)", respectively, and for pointers +we prefer "if (some_pointer != NULL)" or "if (some_pointer == NULL)". We do not use the TAB character for indentation in the C sources. @@ -5849,61 +5927,6 @@ Lines do not exceed 80 characters. Other rules can be inferred by inspecting the libpng source. -.SH XVI. Y2K Compliance in libpng - -Since the PNG Development group is an ad-hoc body, we can't make -an official declaration. - -This is your unofficial assurance that libpng from version 0.71 and -upward through 1.6.23 are Y2K compliant. It is my belief that earlier -versions were also Y2K compliant. - -Libpng only has two year fields. One is a 2-byte unsigned integer -that will hold years up to 65535. The other, which is deprecated, -holds the date in text format, and will hold years up to 9999. - -The integer is - "png_uint_16 year" in png_time_struct. - -The string is - "char time_buffer[29]" in png_struct. This is no longer used -in libpng-1.6.x and will be removed from libpng-1.7.0. - -There are seven time-related functions: - - png_convert_to_rfc_1123_buffer() in png.c - (formerly png_convert_to_rfc_1152() in error, and - also formerly png_convert_to_rfc_1123()) - png_convert_from_struct_tm() in pngwrite.c, called - in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - -All appear to handle dates properly in a Y2K environment. The -png_convert_from_time_t() function calls gmtime() to convert from system -clock time, which returns (year - 1900), which we properly convert to -the full 4-digit year. There is a possibility that applications using -libpng are not passing 4-digit years into the png_convert_to_rfc_1123() -function, or that they are incorrectly passing only a 2-digit year -instead of "year - 1900" into the png_convert_from_struct_tm() function, -but this is not under our control. The libpng documentation has always -stated that it works with 4-digit years, and the APIs have been -documented as such. - -The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned -integer to hold the year, and can hold years as large as 65535. - -zlib, upon which libpng depends, is also Y2K compliant. It contains -no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group - .SH NOTE Note about libpng version numbers: @@ -5914,9 +5937,9 @@ on the library has not always been consistent and straightforward. The following table summarizes matters since version 0.89c, which was the first widely used release: - source png.h png.h shared-lib - version string int version - ------- ------ ----- ---------- + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- 0.89c "1.0 beta 3" 0.89 89 1.0.89 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] @@ -5951,30 +5974,32 @@ the first widely used release: 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) 1.0.7 1 10007 (still compatible) ... - 1.0.19 10 10019 10.so.0.19[.0] + 1.0.69 10 10069 10.so.0.69[.0] ... - 1.2.56 13 10256 12.so.0.56[.0] + 1.2.59 13 10259 12.so.0.59[.0] ... - 1.5.27 15 10527 15.so.15.27[.0] + 1.4.20 14 10420 14.so.0.20[.0] ... - 1.6.23 16 10623 16.so.16.23[.0] + 1.5.30 15 10530 15.so.15.30[.0] + ... + 1.6.35 16 10635 16.so.16.35[.0] -Henceforth the source version will match the shared-library minor -and patch numbers; the shared-library major version number will be -used for changes in backward compatibility, as it is intended. The -PNG_PNGLIB_VER macro, which is not used within libpng but is available -for applications, is an unsigned integer of the form xyyzz corresponding -to the source version x.y.z (leading zeros in y and z). Beta versions -were given the previous public release number plus a letter, until -version 1.0.6j; from then on they were given the upcoming public -release number plus "betaNN" or "rcNN". +Henceforth the source version will match the shared-library minor and +patch numbers; the shared-library major version number will be used for +changes in backward compatibility, as it is intended. +The PNG_PNGLIB_VER macro, which is not used within libpng but is +available for applications, is an unsigned integer of the form XYYZZ +corresponding to the source version X.Y.Z (leading zeros in Y and Z). +Beta versions were given the previous public release number plus a +letter, until version 1.0.6j; from then on they were given the upcoming +public release number plus "betaNN" or "rcNN". .SH "SEE ALSO" .IR libpngpf(3) ", " png(5) .LP .IR libpng : .IP -http://libpng.sourceforge.net (follow the [DOWNLOAD] link) +https://libpng.sourceforge.io/ (follow the [DOWNLOAD] link) http://www.libpng.org/pub/png .LP @@ -5984,7 +6009,7 @@ http://www.libpng.org/pub/png .I libpng or at .br -ftp://ftp.info-zip.org/pub/infozip/zlib +https://zlib.net/ .LP .IR PNG specification: RFC 2083 @@ -5993,19 +6018,20 @@ ftp://ftp.info-zip.org/pub/infozip/zlib .I libpng or at .br -ftp://ftp.rfc-editor.org:/in-notes/rfc2083.txt +https://www.ietf.org/rfc/rfc2083.txt .br or (as a W3C Recommendation) at .br -http://www.w3.org/TR/REC-png.html +https://www.w3.org/TR/REC-png.html .LP In the case of any inconsistency between the PNG specification and this library, the specification takes precedence. .SH AUTHORS -This man page: Glenn Randers-Pehrson - +This man page: +Initially created by Glenn Randers-Pehrson. +Maintained by Cosmin Truta. The contributing authors would like to thank all those who helped with testing, bug fixes, and patience. This wouldn't have been @@ -6013,157 +6039,14 @@ possible without all of you. Thanks to Frank J. T. Wojcik for helping with the documentation. -Libpng version 1.6.23 - June 9, 2016: +Libpng: Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. -Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net). +Maintained by Cosmin Truta. Supported by the PNG development group .br -png-mng-implement at lists.sf.net -(subscription required; visit png-mng-implement at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement to subscribe). -.SH NOTICES: - -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.23, June 9, 2016 are -Copyright (c) 2000-2002, 2004, 2006-2016 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 - -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). - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s", png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -June 9, 2016 - .\" end of man page - diff --git a/source/Irrlicht/libpng/libpng.pc.in b/source/Irrlicht/libpng/libpng.pc.in deleted file mode 100644 index 05ad81ee..00000000 --- a/source/Irrlicht/libpng/libpng.pc.in +++ /dev/null @@ -1,11 +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@ -Libs: -L${libdir} -lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ -Libs.private: @LIBS@ -Cflags: -I${includedir} diff --git a/source/Irrlicht/libpng/libpngpf.3 b/source/Irrlicht/libpng/libpngpf.3 index 9b675246..13b5cf07 100644 --- a/source/Irrlicht/libpng/libpngpf.3 +++ b/source/Irrlicht/libpng/libpngpf.3 @@ -1,18 +1,24 @@ -.TH LIBPNGPF 3 "June 9, 2016" +.TH LIBPNGPF 3 "April 14, 2019" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.6.23 +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.37 (private functions) + .SH SYNOPSIS \fB#include \fI"pngpriv.h" -\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer \fP\fImaintained\fP\fB, now that the private function prototypes are hidden in pngpriv.h and not accessible to applications. Look in pngpriv.h for the prototypes and a short description of each \fIfunction. +\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer +\fP\fImaintained\fP\fB, now that the private function prototypes are hidden in +\fP\fIpngpriv.h\fP\fB and not accessible to applications. Look in +\fP\fIpngpriv.h\fP\fB for the prototypes and a short description of each +function. .SH DESCRIPTION The functions previously listed here are used privately by libpng and are not available for use by applications. They are not "exported" to applications using shared libraries. -.SH SEE ALSO +.SH "SEE ALSO" .BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) -.SH AUTHOR -Glenn Randers-Pehrson + +.SH AUTHORS +Cosmin Truta, Glenn Randers-Pehrson diff --git a/source/Irrlicht/libpng/png.5 b/source/Irrlicht/libpng/png.5 index 7c0b9a46..fa025f89 100644 --- a/source/Irrlicht/libpng/png.5 +++ b/source/Irrlicht/libpng/png.5 @@ -1,47 +1,49 @@ -.TH PNG 5 "June 9, 2016" +.TH PNG 5 "April 14, 2019" .SH NAME png \- Portable Network Graphics (PNG) format + .SH DESCRIPTION PNG (Portable Network Graphics) is an extensible file format for the -lossless, portable, well-compressed storage of raster images. PNG provides -a patent-free replacement for GIF and can also replace many +lossless, portable, well-compressed storage of raster images. PNG +provides a patent-free replacement for GIF, and can also replace many common uses of TIFF. Indexed-color, grayscale, and truecolor images are -supported, plus an optional alpha channel. Sample depths range from +supported, plus an optional alpha channel. Sample depths range from 1 to 16 bits. .br - -PNG is designed to work well in online viewing applications, such as the -World Wide Web, so it is fully streamable with a progressive display -option. PNG is robust, providing both full file integrity checking and -fast, simple detection of common transmission errors. Also, PNG can store -gamma and chromaticity data for improved color matching on heterogeneous -platforms. +PNG is designed to work well in online viewing applications, such +as the World Wide Web, so it is fully streamable with a progressive +display option. PNG is robust, providing both full file integrity +checking and fast, simple detection of common transmission errors. +Also, PNG can store gamma and chromaticity data for improved color +matching on heterogeneous platforms. .SH "SEE ALSO" .BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) .LP -PNG specification (second edition), November 2003: +PNG Specification (Second Edition), November 2003: .IP .br - = (~(png_alloc_size_t)0)/size) { png_warning (png_voidcast(png_structrp, png_ptr), - "Potential overflow in png_zalloc()"); + "Potential overflow in png_zalloc()"); return NULL; } @@ -116,7 +136,7 @@ png_reset_crc(png_structrp png_ptr) * trouble of calculating it. */ void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length) { int need_crc = 1; @@ -172,10 +192,10 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) int png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) { - /* Libpng versions 1.0.0 and later are binary compatible if the version - * string matches through the second '.'; we must recompile any - * applications that use any older library version. - */ + /* Libpng versions 1.0.0 and later are binary compatible if the version + * string matches through the second '.'; we must recompile any + * applications that use any older library version. + */ if (user_png_ver != NULL) { @@ -297,7 +317,7 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, if (png_user_version_check(&create_struct, user_png_ver) != 0) { png_structrp png_ptr = png_voidcast(png_structrp, - png_malloc_warn(&create_struct, (sizeof *png_ptr))); + png_malloc_warn(&create_struct, (sizeof *png_ptr))); if (png_ptr != NULL) { @@ -346,7 +366,7 @@ png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) * has always been done in 'example.c'. */ info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, - (sizeof *info_ptr))); + (sizeof *info_ptr))); if (info_ptr != NULL) memset(info_ptr, 0, (sizeof *info_ptr)); @@ -401,8 +421,8 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) * those cases where it does anything other than a memset. */ PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), - PNG_DEPRECATED) +png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size), + PNG_DEPRECATED) { png_inforp info_ptr = *ptr_ptr; @@ -417,7 +437,7 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), /* The following line is why this API should not be used: */ free(info_ptr); info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, - (sizeof *info_ptr))); + (sizeof *info_ptr))); if (info_ptr == NULL) return; *ptr_ptr = info_ptr; @@ -430,7 +450,7 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), /* The following API is not called internally */ void PNGAPI png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, - int freer, png_uint_32 mask) + int freer, png_uint_32 mask) { png_debug(1, "in png_data_freer"); @@ -449,7 +469,7 @@ png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, void PNGAPI png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, - int num) + int num) { png_debug(1, "in png_free_data"); @@ -458,7 +478,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #ifdef PNG_TEXT_SUPPORTED /* Free text item num or (if num == -1) all text items */ - if (info_ptr->text != 0 && + if (info_ptr->text != NULL && ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0) { if (num != -1) @@ -477,6 +497,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, png_free(png_ptr, info_ptr->text); info_ptr->text = NULL; info_ptr->num_text = 0; + info_ptr->max_text = 0; } } #endif @@ -541,7 +562,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #ifdef PNG_sPLT_SUPPORTED /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ - if (info_ptr->splt_palettes != 0 && + if (info_ptr->splt_palettes != NULL && ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0) { if (num != -1) @@ -571,7 +592,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #endif #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - if (info_ptr->unknown_chunks != 0 && + if (info_ptr->unknown_chunks != NULL && ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0) { if (num != -1) @@ -594,6 +615,26 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, } #endif +#ifdef PNG_eXIf_SUPPORTED + /* Free any eXIf entry */ + if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) + { +# ifdef PNG_READ_eXIf_SUPPORTED + if (info_ptr->eXIf_buf) + { + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + } +# endif + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + info_ptr->valid &= ~PNG_INFO_eXIf; + } +#endif + #ifdef PNG_hIST_SUPPORTED /* Free any hIST entry */ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) @@ -617,7 +658,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, /* Free any image bits attached to the info structure */ if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0) { - if (info_ptr->row_pointers != 0) + if (info_ptr->row_pointers != NULL) { png_uint_32 row; for (row = 0; row < info_ptr->height; row++) @@ -684,7 +725,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) { - png_save_uint_32(buf, i); + png_save_uint_32(buf, (png_uint_32)i); } # endif @@ -695,7 +736,7 @@ png_save_int_32(png_bytep buf, png_int_32 i) int PNGAPI png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) { - static PNG_CONST char short_months[12][4] = + static const char short_months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; @@ -773,20 +814,14 @@ png_get_copyright(png_const_structrp png_ptr) #ifdef PNG_STRING_COPYRIGHT return PNG_STRING_COPYRIGHT #else -# ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.23 - June 9, 2016" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ + "libpng version 1.6.37" PNG_STRING_NEWLINE \ + "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; -# else - return "libpng version 1.6.23 - June 9, 2016\ - Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ - Copyright (c) 1996-1997 Andreas Dilger\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; -# endif #endif } @@ -901,7 +936,7 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) /* The code is the fifth byte after each four byte string. Historically this * code was always searched from the end of the list, this is no longer - * necessary because the 'set' routine handles duplicate entries correcty. + * necessary because the 'set' routine handles duplicate entries correctly. */ do /* num_chunk_list > 0, so at least one */ { @@ -1033,7 +1068,7 @@ png_zstream_error(png_structrp png_ptr, int ret) #ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ static int png_colorspace_check_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA, int from) + png_colorspacerp colorspace, png_fixed_point gAMA, int from) /* This is called to check a new gamma value against an existing one. The * routine returns false if the new gamma value should not be written. * @@ -1047,7 +1082,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, png_fixed_point gtest; if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || + (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || png_gamma_significant(gtest) != 0)) { /* Either this is an sRGB image, in which case the calculated gamma @@ -1059,7 +1094,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) { png_chunk_report(png_ptr, "gamma value does not match sRGB", - PNG_CHUNK_ERROR); + PNG_CHUNK_ERROR); /* Do not overwrite an sRGB value */ return from == 2; } @@ -1067,7 +1102,7 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, else /* sRGB tag not involved */ { png_chunk_report(png_ptr, "gamma value does not match libpng estimate", - PNG_CHUNK_WARNING); + PNG_CHUNK_WARNING); return from == 1; } } @@ -1077,10 +1112,10 @@ png_colorspace_check_gamma(png_const_structrp png_ptr, void /* PRIVATE */ png_colorspace_set_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA) + png_colorspacerp colorspace, png_fixed_point gAMA) { /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't - * occur. Since the fixed point representation is asymetrical it is + * occur. Since the fixed point representation is asymmetrical it is * possible for 1/gamma to overflow the limit of 21474 and this means the * gamma value must be at least 5/100000 and hence at most 20000.0. For * safety the limits here are a little narrower. The values are 0.00016 to @@ -1635,8 +1670,8 @@ static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ static int png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, - int preferred) + png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, + int preferred) { if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; @@ -1683,7 +1718,7 @@ png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, int /* PRIVATE */ png_colorspace_set_chromaticities(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, int preferred) + png_colorspacerp colorspace, const png_xy *xy, int preferred) { /* We must check the end points to ensure they are reasonable - in the past * color management systems have crashed as a result of getting bogus @@ -1697,7 +1732,7 @@ png_colorspace_set_chromaticities(png_const_structrp png_ptr, { case 0: /* success */ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, - preferred); + preferred); case 1: /* We can't invert the chromaticities so we can't produce value XYZ @@ -1720,7 +1755,7 @@ png_colorspace_set_chromaticities(png_const_structrp png_ptr, int /* PRIVATE */ png_colorspace_set_endpoints(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) + png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) { png_XYZ XYZ = *XYZ_in; png_xy xy; @@ -1729,7 +1764,7 @@ png_colorspace_set_endpoints(png_const_structrp png_ptr, { case 0: return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, - preferred); + preferred); case 1: /* End points are invalid. */ @@ -1786,7 +1821,7 @@ is_ICC_signature(png_alloc_size_t it) static int png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_alloc_size_t value, png_const_charp reason) + png_const_charp name, png_alloc_size_t value, png_const_charp reason) { size_t pos; char message[196]; /* see below for calculation */ @@ -1811,8 +1846,8 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ pos = png_safecat(message, (sizeof message), pos, - png_format_number(number, number+(sizeof number), - PNG_NUMBER_FORMAT_x, value)); + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ } # endif @@ -1826,7 +1861,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, * application errors the PNG won't be written.) */ png_chunk_report(png_ptr, message, - (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); + (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); return 0; } @@ -1835,7 +1870,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, #ifdef PNG_sRGB_SUPPORTED int /* PRIVATE */ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, - int intent) + int intent) { /* sRGB sets known gamma, end points and (from the chunk) intent. */ /* IMPORTANT: these are not necessarily the values found in an ICC profile @@ -1872,12 +1907,12 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); + (png_alloc_size_t)intent, "invalid sRGB rendering intent"); if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && - colorspace->rendering_intent != intent) + colorspace->rendering_intent != intent) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); + (png_alloc_size_t)intent, "inconsistent rendering intents"); if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) { @@ -1889,8 +1924,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, * warn but overwrite the value with the correct one. */ if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && - !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, - 100)) + !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, + 100)) png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", PNG_CHUNK_ERROR); @@ -1898,7 +1933,7 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, * returns true when the 'from' argument corresponds to sRGB (2). */ (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, - 2/*from sRGB*/); + 2/*from sRGB*/); /* intent: bugs in GCC force 'int' to be used as the parameter type. */ colorspace->rendering_intent = (png_uint_16)intent; @@ -1931,21 +1966,54 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, static const png_byte D50_nCIEXYZ[12] = { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; -int /* PRIVATE */ -png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length) +static int /* bool */ +icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) { if (profile_length < 132) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "too short"); - + "too short"); return 1; } +#ifdef PNG_READ_iCCP_SUPPORTED +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (!icc_check_length(png_ptr, colorspace, name, profile_length)) + return 0; + + /* This needs to be here because the 'normal' check is in + * png_decompress_chunk, yet this happens after the attempt to + * png_malloc_base the required data. We only need this on read; on write + * the caller supplies the profile buffer so libpng doesn't allocate it. See + * the call to icc_check_length below (the write case). + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + else if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds application limits"); +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds libpng limits"); +# else /* !SET_USER_LIMITS */ + /* This will get compiled out on all 32-bit and better systems. */ + else if (PNG_SIZE_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds system limits"); +# endif /* !SET_USER_LIMITS */ + + return 1; +} +#endif /* READ_iCCP */ + int /* PRIVATE */ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile/* first 132 bytes only */, int color_type) + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile/* first 132 bytes only */, int color_type) { png_uint_32 temp; @@ -1957,18 +2025,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile); if (temp != profile_length) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "length does not match profile"); + "length does not match profile"); temp = (png_uint_32) (*(profile+8)); if (temp > 3 && (profile_length & 3)) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "invalid length"); + "invalid length"); temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ profile_length < 132+12*temp) /* truncated tag table */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "tag count too large"); + "tag count too large"); /* The 'intent' must be valid or we can't store it, ICC limits the intent to * 16 bits. @@ -1976,14 +2044,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile+64); if (temp >= 0xffff) /* The ICC limit */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid rendering intent"); + "invalid rendering intent"); /* This is just a warning because the profile may be valid in future * versions. */ if (temp >= PNG_sRGB_INTENT_LAST) (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "intent outside defined range"); + "intent outside defined range"); /* At this point the tag table can't be checked because it hasn't necessarily * been loaded; however, various header fields can be checked. These checks @@ -1993,14 +2061,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ /* Data checks (could be skipped). These checks must be independent of the - * version number; however, the version number doesn't accomodate changes in + * version number; however, the version number doesn't accommodate changes in * the header fields (just the known tags and the interpretation of the * data.) */ temp = png_get_uint_32(profile+36); /* signature 'ascp' */ if (temp != 0x61637370) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid signature"); + "invalid signature"); /* Currently the PCS illuminant/adopted white point (the computational * white point) are required to be D50, @@ -2011,7 +2079,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, - "PCS illuminant is not D50"); + "PCS illuminant is not D50"); /* The PNG spec requires this: * "If the iCCP chunk is present, the image samples conform to the colour @@ -2039,18 +2107,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, case 0x52474220: /* 'RGB ' */ if ((color_type & PNG_COLOR_MASK_COLOR) == 0) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "RGB color space not permitted on grayscale PNG"); + "RGB color space not permitted on grayscale PNG"); break; case 0x47524159: /* 'GRAY' */ if ((color_type & PNG_COLOR_MASK_COLOR) != 0) return png_icc_profile_error(png_ptr, colorspace, name, temp, - "Gray color space not permitted on RGB PNG"); + "Gray color space not permitted on RGB PNG"); break; default: return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid ICC profile color space"); + "invalid ICC profile color space"); } /* It is up to the application to check that the profile class matches the @@ -2075,7 +2143,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, case 0x61627374: /* 'abst' */ /* May not be embedded in an image */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid embedded Abstract ICC profile"); + "invalid embedded Abstract ICC profile"); case 0x6c696e6b: /* 'link' */ /* DeviceLink profiles cannot be interpreted in a non-device specific @@ -2085,7 +2153,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * PNG. */ return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected DeviceLink ICC profile class"); + "unexpected DeviceLink ICC profile class"); case 0x6e6d636c: /* 'nmcl' */ /* A NamedColor profile is also device specific, however it doesn't @@ -2093,7 +2161,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * certainly it will fail the tests below. */ (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unexpected NamedColor ICC profile class"); + "unexpected NamedColor ICC profile class"); break; default: @@ -2103,7 +2171,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * understood profiles. */ (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unrecognized ICC profile class"); + "unrecognized ICC profile class"); break; } @@ -2119,7 +2187,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, default: return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected ICC PCS encoding"); + "unexpected ICC PCS encoding"); } return 1; @@ -2127,8 +2195,8 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, int /* PRIVATE */ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */) + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */) { png_uint_32 tag_count = png_get_uint_32(profile+128); png_uint_32 itag; @@ -2149,22 +2217,23 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, * being in range. All defined tag types have an 8 byte header - a 4 byte * type signature then 0. */ - if ((tag_start & 3) != 0) - { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is - * only a warning here because libpng does not care about the - * alignment. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "ICC profile tag start not a multiple of 4"); - } /* This is a hard error; potentially it can cause read outside the * profile. */ if (tag_start > profile_length || tag_length > profile_length - tag_start) return png_icc_profile_error(png_ptr, colorspace, name, tag_id, - "ICC profile tag outside profile"); + "ICC profile tag outside profile"); + + if ((tag_start & 3) != 0) + { + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is + * only a warning here because libpng does not care about the + * alignment. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, + "ICC profile tag start not a multiple of 4"); + } } return 1; /* success, maybe with warnings */ @@ -2192,22 +2261,22 @@ static const struct */ /* adler32, crc32, MD5[4], intent, date, length, file-name */ PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, - PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, - "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") + PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, + "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") /* ICC sRGB v2 perceptual no black-compensation: */ PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, - PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, - "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") + PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, + "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, - PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, - "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") + PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, + "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") /* ICC sRGB v4 perceptual */ PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, - PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, - "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") + PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, + "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") /* The following profiles have no known MD5 checksum. If there is a match * on the (empty) MD5 the other fields are used to attempt a match and @@ -2215,8 +2284,8 @@ static const struct * which suggests that they were also made by Hewlett Packard. */ PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, - "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, + "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not * match the D50 PCS illuminant in the header (it is in fact the D65 values, @@ -2226,17 +2295,17 @@ static const struct * chromaticAdaptationTag. */ PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") }; static int png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, - png_const_bytep profile, uLong adler) + png_const_bytep profile, uLong adler) { /* The quick check is to verify just the MD5 signature and trust the * rest of the data. Because the profile has already been verified for @@ -2320,7 +2389,7 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, * which is made irrelevant by this error. */ png_chunk_report(png_ptr, "known incorrect sRGB profile", - PNG_CHUNK_ERROR); + PNG_CHUNK_ERROR); } /* Warn that this being done; this isn't even an error since @@ -2330,8 +2399,8 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, else if (png_sRGB_checks[i].have_md5 == 0) { png_chunk_report(png_ptr, - "out-of-date sRGB profile with no signature", - PNG_CHUNK_WARNING); + "out-of-date sRGB profile with no signature", + PNG_CHUNK_WARNING); } return 1+png_sRGB_checks[i].is_broken; @@ -2354,38 +2423,36 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, return 0; /* no match */ } -#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ void /* PRIVATE */ png_icc_set_sRGB(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_bytep profile, uLong adler) + png_colorspacerp colorspace, png_const_bytep profile, uLong adler) { /* Is this profile one of the known ICC sRGB profiles? If it is, just set * the sRGB information. */ -#if PNG_sRGB_PROFILE_CHECKS >= 0 if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) -#endif (void)png_colorspace_set_sRGB(png_ptr, colorspace, (int)/*already checked*/png_get_uint_32(profile+64)); } +#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ #endif /* sRGB */ int /* PRIVATE */ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, - int color_type) + png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, + int color_type) { if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; - if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, - color_type) != 0 && + color_type) != 0 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, - profile) != 0) + profile) != 0) { -# ifdef PNG_sRGB_SUPPORTED +# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 /* If no sRGB support, don't try storing sRGB information */ png_icc_set_sRGB(png_ptr, colorspace, profile, 0); # endif @@ -2444,7 +2511,7 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) /* Check for an internal error. */ if (r+g+b != 32768) png_error(png_ptr, - "internal error handling cHRM coefficients"); + "internal error handling cHRM coefficients"); else { @@ -2470,7 +2537,7 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) static int /* PRIVATE */ png_gt(size_t a, size_t b) { - return a > b; + return a > b; } #else # define png_gt(a,b) ((a) > (b)) @@ -2478,9 +2545,9 @@ png_gt(size_t a, size_t b) void /* PRIVATE */ png_check_IHDR(png_const_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) { int error = 0; @@ -2497,7 +2564,7 @@ png_check_IHDR(png_const_structrp png_ptr, error = 1; } - if (png_gt(((width + 7) & (~7)), + if (png_gt(((width + 7) & (~7U)), ((PNG_SIZE_MAX - 48 /* big_row_buf hack */ - 1) /* filter byte */ @@ -2634,7 +2701,7 @@ png_check_IHDR(png_const_structrp png_ptr, #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) /* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed +/* Check an ASCII formatted floating point value, see the more detailed * comments in pngpriv.h */ /* The following is used internally to preserve the sticky flags */ @@ -2642,11 +2709,11 @@ png_check_IHDR(png_const_structrp png_ptr, #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, - png_size_tp whereami) +png_check_fp_number(png_const_charp string, size_t size, int *statep, + png_size_tp whereami) { int state = *statep; - png_size_t i = *whereami; + size_t i = *whereami; while (i < size) { @@ -2769,10 +2836,10 @@ PNG_FP_End: /* The same but for a complete string. */ int -png_check_fp_string(png_const_charp string, png_size_t size) +png_check_fp_string(png_const_charp string, size_t size) { int state=0; - png_size_t char_index=0; + size_t char_index=0; if (png_check_fp_number(string, size, &state, &char_index) != 0 && (char_index == size || string[char_index] == 0)) @@ -2799,7 +2866,7 @@ png_pow10(int power) if (power < 0) { if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; + recip = 1; power = -power; } if (power > 0) @@ -2824,8 +2891,16 @@ png_pow10(int power) /* Function to format a floating point value in ASCII with a given * precision. */ +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic push +/* The problem arises below with exp_b10, which can never overflow because it + * comes, originally, from frexp and is therefore limited to a range which is + * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)). + */ +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, double fp, unsigned int precision) { /* We use standard functions from math.h, but not printf because @@ -2877,7 +2952,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, double test = png_pow10(exp_b10+1); if (test <= DBL_MAX) - ++exp_b10, base = test; + { + ++exp_b10; base = test; + } else break; @@ -2891,7 +2968,10 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * test on DBL_MAX above. */ fp /= base; - while (fp >= 1) fp /= 10, ++exp_b10; + while (fp >= 1) + { + fp /= 10; ++exp_b10; + } /* Because of the code above fp may, at this point, be * less than .1, this is ok because the code below can @@ -2908,7 +2988,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ { - czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */ exp_b10 = 0; /* Dot added below before first output. */ } else @@ -2942,7 +3022,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Rounding up to 10, handle that here. */ if (czero > 0) { - --czero, d = 1; + --czero; d = 1; if (cdigits == 0) --clead; } else @@ -2956,7 +3036,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, else if (ch == 46) { - ch = *--ascii, ++size; + ch = *--ascii; ++size; /* Advance exp_b10 to '1', so that the * decimal point happens after the * previous digit. @@ -2983,7 +3063,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, int ch = *--ascii; if (ch == 46) - ++size, exp_b10 = 1; + { + ++size; exp_b10 = 1; + } /* Else lost a leading zero, so 'exp_b10' is * still ok at (-1) @@ -3019,21 +3101,26 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ if (exp_b10 != (-1)) { - if (exp_b10 == 0) *ascii++ = 46, --size; + if (exp_b10 == 0) + { + *ascii++ = 46; --size; + } /* PLUS 1: TOTAL 4 */ --exp_b10; } - *ascii++ = 48, --czero; + *ascii++ = 48; --czero; } if (exp_b10 != (-1)) { if (exp_b10 == 0) - *ascii++ = 46, --size; /* counted above */ + { + *ascii++ = 46; --size; /* counted above */ + } --exp_b10; } - *ascii++ = (char)(48 + (int)d), ++cdigits; + *ascii++ = (char)(48 + (int)d); ++cdigits; } } while (cdigits+czero < precision+clead && fp > DBL_MIN); @@ -3041,11 +3128,11 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* The total output count (max) is now 4+precision */ /* Check for an exponent, if we don't need one we are - * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got - * to '-1' because of the decrement after outputting - * the decimal point above (the exponent required is - * *not* -1!) + * done and just need to terminate the string. At this + * point, exp_b10==(-1) is effectively a flag: it got + * to '-1' because of the decrement, after outputting + * the decimal point above. (The exponent required is + * *not* -1.) */ if (exp_b10 >= (-1) && exp_b10 <= 2) { @@ -3056,7 +3143,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * zeros were *not* output, so this doesn't increase * the output count. */ - while (--exp_b10 >= 0) *ascii++ = 48; + while (exp_b10-- > 0) *ascii++ = 48; *ascii = 0; @@ -3074,7 +3161,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ size -= cdigits; - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + *ascii++ = 69; --size; /* 'E': PLUS 1 TOTAL 2+precision */ /* The following use of an unsigned temporary avoids ambiguities in * the signed arithmetic on exp_b10 and permits GCC at least to do @@ -3085,12 +3172,12 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, if (exp_b10 < 0) { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = -exp_b10; + *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = 0U-exp_b10; } else - uexp_b10 = exp_b10; + uexp_b10 = 0U+exp_b10; cdigits = 0; @@ -3133,6 +3220,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Here on buffer too small. */ png_error(png_ptr, "ASCII conversion buffer too small"); } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ # endif /* FLOATING_POINT */ @@ -3141,7 +3231,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ void /* PRIVATE */ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) + size_t size, png_fixed_point fp) { /* Require space for 10 decimal digits, a decimal point, a minus sign and a * trailing \0, 13 characters: @@ -3152,9 +3242,11 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, /* Avoid overflow here on the minimum integer. */ if (fp < 0) - *ascii++ = 45, num = -fp; + { + *ascii++ = 45; num = (png_uint_32)(-fp); + } else - num = fp; + num = (png_uint_32)fp; if (num <= 0x80000000) /* else overflowed */ { @@ -3190,7 +3282,10 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, * then ndigits digits to first: */ i = 5; - while (ndigits < i) *ascii++ = 48, --i; + while (ndigits < i) + { + *ascii++ = 48; --i; + } while (ndigits >= first) *ascii++ = digits[--ndigits]; /* Don't output the trailing zeros! */ } @@ -3241,6 +3336,15 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) * the nearest .00001). Overflow and divide by zero are signalled in * the result, a boolean - true on success, false on overflow. */ +#if GCC_STRICT_OVERFLOW /* from above */ +/* It is not obvious which comparison below gets optimized in such a way that + * signed overflow would change the result; looking through the code does not + * reveal any tests which have the form GCC complains about, so presumably the + * optimizer is moving an add or subtract into the 'if' somewhere. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ int png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, png_int_32 divisor) @@ -3355,6 +3459,9 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, return 0; } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ #endif /* READ_GAMMA || INCH_CONVERSIONS */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) @@ -3648,7 +3755,7 @@ png_log16bit(png_uint_32 x) * of getting this accuracy in practice. * * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the + * fractional part of the logarithm by using an accurate 32-bit value from the * top four fractional bits then multiplying in the remaining bits. */ static const png_uint_32 @@ -3806,25 +3913,25 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) { if (value > 0 && value < 65535) { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - /* The same (unsigned int)->(double) constraints apply here as above, - * however in this case the (unsigned int) to (int) conversion can - * overflow on an ANSI-C90 compliant system so the cast needs to ensure - * that this is not possible. - */ - double r = floor(65535*pow((png_int_32)value/65535., - gamma_val*.00001)+.5); - return (png_uint_16)r; -# else - png_int_32 lg2 = png_log16bit(value); - png_fixed_point res; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* The same (unsigned int)->(double) constraints apply here as above, + * however in this case the (unsigned int) to (int) conversion can + * overflow on an ANSI-C90 compliant system so the cast needs to ensure + * that this is not possible. + */ + double r = floor(65535*pow((png_int_32)value/65535., + gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) - return png_exp16bit(res); + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) + return png_exp16bit(res); - /* Overflow. */ - value = 0; -# endif + /* Overflow. */ + value = 0; +# endif } return (png_uint_16)value; @@ -3863,18 +3970,18 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value, */ static void png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + unsigned int shift, png_fixed_point gamma_val) { /* Various values derived from 'shift': */ - PNG_CONST unsigned int num = 1U << (8U - shift); + unsigned int num = 1U << (8U - shift); #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* CSE the division and work round wacky GCC warnings (see the comments * in png_gamma_8bit_correct for where these come from.) */ - PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1); + double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1); #endif - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int max = (1U << (16U - shift)) - 1U; + unsigned int max_by_2 = 1U << (15U - shift); unsigned int i; png_uint_16pp table = *ptable = @@ -3940,10 +4047,10 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + unsigned int shift, png_fixed_point gamma_val) { - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int num = 1U << (8U - shift); + unsigned int max = (1U << (16U - shift))-1U; unsigned int i; png_uint_32 last; @@ -4008,7 +4115,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) + png_fixed_point gamma_val) { unsigned int i; png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); @@ -4088,131 +4195,133 @@ png_destroy_gamma_table(png_structrp png_ptr) void /* PRIVATE */ png_build_gamma_table(png_structrp png_ptr, int bit_depth) { - png_debug(1, "in png_build_gamma_table"); + png_debug(1, "in png_build_gamma_table"); - /* Remove any existing table; this copes with multiple calls to - * png_read_update_info. The warning is because building the gamma tables - * multiple times is a performance hit - it's harmless but the ability to call - * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible - * to warn if the app introduces such a hit. - */ - if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) - { - png_warning(png_ptr, "gamma table being rebuilt"); - png_destroy_gamma_table(png_ptr); - } + /* Remove any existing table; this copes with multiple calls to + * png_read_update_info. The warning is because building the gamma tables + * multiple times is a performance hit - it's harmless but the ability to + * call png_read_update_info() multiple times is new in 1.5.6 so it seems + * sensible to warn if the app introduces such a hit. + */ + if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) + { + png_warning(png_ptr, "gamma table being rebuilt"); + png_destroy_gamma_table(png_ptr); + } - if (bit_depth <= 8) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_table, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? + png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->colorspace.gamma)); + if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->colorspace.gamma)); - png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } + } #ifdef PNG_16BIT_SUPPORTED - else - { - png_byte shift, sig_bit; + else + { + png_byte shift, sig_bit; - if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) - { - sig_bit = png_ptr->sig_bit.red; + if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) + { + sig_bit = png_ptr->sig_bit.red; - if (png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; - if (png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - sig_bit = png_ptr->sig_bit.gray; + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; - /* 16-bit gamma code uses this equation: - * - * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] - * - * Where 'iv' is the input color value and 'ov' is the output value - - * pow(iv, gamma). - * - * Thus the gamma table consists of up to 256 256-entry tables. The table - * is selected by the (8-gamma_shift) most significant of the low 8 bits of - * the color value then indexed by the upper 8 bits: - * - * table[low bits][high 8 bits] - * - * So the table 'n' corresponds to all those 'iv' of: - * - * ..<(n+1 << gamma_shift)-1> - * - */ - if (sig_bit > 0 && sig_bit < 16U) - /* shift == insignificant bits */ - shift = (png_byte)((16U - sig_bit) & 0xff); + /* 16-bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256-entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits + * of the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + /* shift == insignificant bits */ + shift = (png_byte)((16U - sig_bit) & 0xff); - else - shift = 0; /* keep all 16 bits */ + else + shift = 0; /* keep all 16 bits */ - if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) - { - /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively - * the significant bits in the *input* when the output will - * eventually be 8 bits. By default it is 11. - */ - if (shift < (16U - PNG_MAX_GAMMA_8)) - shift = (16U - PNG_MAX_GAMMA_8); - } + if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } - if (shift > 8U) - shift = 8U; /* Guarantees at least one table! */ + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ - png_ptr->gamma_shift = shift; + png_ptr->gamma_shift = shift; - /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now - * PNG_COMPOSE). This effectively smashed the background calculation for - * 16-bit output because the 8-bit table assumes the result will be reduced - * to 8 bits. - */ - if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) - png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be + * reduced to 8 bits. + */ + if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); - else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) - { - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->colorspace.gamma)); + if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->colorspace.gamma)); - /* Notice that the '16 from 1' table should be full precision, however - * the lookup on this table still uses gamma_shift, so it can't be. - * TODO: fix this. - */ - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } + } #endif /* 16BIT */ } #endif /* READ_GAMMA */ @@ -4225,13 +4334,13 @@ png_set_option(png_structrp png_ptr, int option, int onoff) if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && (option & 1) == 0) { - int mask = 3 << option; - int setting = (2 + (onoff != 0)) << option; - int current = png_ptr->options; + png_uint_32 mask = 3U << option; + png_uint_32 setting = (2U + (onoff != 0)) << option; + png_uint_32 current = png_ptr->options; - png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff); + png_ptr->options = (png_uint_32)((current & ~mask) | setting); - return (current & mask) >> option; + return (int)(current & mask) >> option; } return PNG_OPTION_INVALID; @@ -4243,7 +4352,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff) defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* sRGB conversion tables; these are machine generated with the code in * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the - * specification (see the article at http://en.wikipedia.org/wiki/SRGB) + * specification (see the article at https://en.wikipedia.org/wiki/SRGB) * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The inverse (linear to sRGB) table has accuracies as follows: @@ -4479,8 +4588,7 @@ png_image_free(png_imagep image) if (image != NULL && image->opaque != NULL && image->opaque->error_buf == NULL) { - /* Ignore errors here: */ - (void)png_safe_execute(image, png_image_free_function, image); + png_image_free_function(image); image->opaque = NULL; } } diff --git a/source/Irrlicht/libpng/png.h b/source/Irrlicht/libpng/png.h index 04648c7a..1cc28bfe 100644 --- a/source/Irrlicht/libpng/png.h +++ b/source/Irrlicht/libpng/png.h @@ -1,72 +1,105 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.23, June 9, 2016 + * libpng version 1.6.37 - April 14, 2019 * - * 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * - * This code is released under the libpng license (See LICENSE, below) + * This code is released under the libpng license. (See LICENSE, below.) * * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.23, June 9, 2016: - * Glenn Randers-Pehrson. + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019: + * Cosmin Truta * See also "Contributing Authors", below. */ /* - * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= * - * If you modify libpng you may insert additional notices immediately following - * this sentence. + * PNG Reference Library License version 2 + * --------------------------------------- * - * This code is released under the libpng license. + * * Copyright (c) 1995-2019 The PNG Reference Library Authors. + * * Copyright (c) 2018-2019 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * - * 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. + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are - * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 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 + * 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. + * 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 have other copyright owners and + * 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: + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: * - * Tom Lane - * Glenn Randers-Pehrson - * Willem van Schaik - * - * Some files in the "scripts" directory have different copyright owners - * but are also released under this license. + * 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, @@ -74,14 +107,14 @@ * 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 + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner * - * Some files in the "scripts" directory have other copyright owners + * 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 @@ -90,62 +123,49 @@ * 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 + * 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. + * 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. + * 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. + * 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. + * 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. + * 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: + * TRADEMARK + * ========= * - * The name "libpng" has not been registered by the Copyright owner + * The name "libpng" has not been registered by the Copyright owners * 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 + * the Copyright owners claim "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). */ /* @@ -211,23 +231,25 @@ * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) * 1.0.7 1 10007 (still compatible) * ... - * 1.0.19 10 10019 10.so.0.19[.0] + * 1.0.69 10 10069 10.so.0.69[.0] * ... - * 1.2.56 13 10256 12.so.0.56[.0] + * 1.2.59 13 10259 12.so.0.59[.0] * ... - * 1.5.27 15 10527 15.so.15.27[.0] + * 1.4.20 14 10420 14.so.0.20[.0] * ... - * 1.6.23 16 10623 16.so.16.23[.0] + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.37 16 10637 16.so.16.37[.0] * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcNN". + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". * * Binary incompatibility exists only when applications make direct access * to the info_ptr or png_ptr members through png.h, and the compiled @@ -237,65 +259,8 @@ * in binary compatibility (e.g., when a new feature is added). * * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * */ #ifndef PNG_H @@ -313,9 +278,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.23" -#define PNG_HEADER_VERSION_STRING \ - " libpng version 1.6.23 - June 9, 2016\n" +#define PNG_LIBPNG_VER_STRING "1.6.37" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -323,12 +287,11 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 23 +#define PNG_LIBPNG_VER_RELEASE 37 -/* This should match the numeric part of the final component of - * PNG_LIBPNG_VER_STRING, omitting any leading zero: +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] */ - #define PNG_LIBPNG_VER_BUILD 0 /* Release Status */ @@ -348,26 +311,27 @@ #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE -/* Careful here. At one time, Guy wanted to use 082, but that would be octal. - * We must not include leading zeros. - * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only - * version 1.0.0 was mis-numbered 100 instead of 10000). From - * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10623 /* 1.6.23 */ +#define PNG_LIBPNG_VER 10637 /* 1.6.37 */ /* Library configuration: these options cannot be changed after * the library has been built. */ #ifndef PNGLCONF_H - /* If pnglibconf.h is missing, you can - * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h - */ +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ # include "pnglibconf.h" #endif #ifndef PNG_VERSION_INFO_ONLY - /* Machine specific configuration. */ +/* Machine specific configuration. */ # include "pngconf.h" #endif @@ -464,7 +428,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_23; +typedef char* png_libpng_version_1_6_37; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -605,8 +569,8 @@ typedef struct png_text_struct png_charp key; /* keyword, 1-79 character description of "text" */ png_charp text; /* comment, may be an empty string (ie "") or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ png_charp lang; /* language code, 0-79 characters or a NULL pointer */ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more @@ -657,17 +621,17 @@ typedef png_time * * png_timepp; */ typedef struct png_unknown_chunk_t { - png_byte name[5]; /* Textual chunk name with '\0' terminator */ - png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; - /* On write 'location' must be set using the flag values listed below. - * Notice that on read it is set by libpng however the values stored have - * more bits set than are listed below. Always treat the value as a - * bitmask. On write set only one bit - setting multiple bits may cause the - * chunk to be written in multiple places. - */ - png_byte location; /* mode of operation at read time */ + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ } png_unknown_chunk; @@ -684,7 +648,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) /* These are constants for fixed point values encoded in the * PNG specification manner (x100000) @@ -781,6 +745,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; #define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -789,7 +754,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; typedef struct png_row_info_struct { png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ + size_t rowbytes; /* number of bytes in row */ png_byte color_type; /* color type of row */ png_byte bit_depth; /* bit depth of row */ png_byte channels; /* number of channels (1, 2, 3, or 4) */ @@ -808,7 +773,7 @@ typedef png_row_info * * png_row_infopp; * expected to return the read data in the buffer. */ typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, int)); @@ -945,8 +910,8 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); /* Simple signature checking function. This is the same as calling * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). @@ -965,11 +930,11 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct, png_error_ptr warn_fn), PNG_ALLOCATED); -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, (png_const_structrp png_ptr)); PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); + size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp * match up. @@ -1022,7 +987,7 @@ PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); /* Write a PNG chunk - size, type, (optional) data, CRC. */ PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); + chunk_name, png_const_bytep data, size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, @@ -1030,7 +995,7 @@ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, /* Write the data of a PNG chunk started with png_write_chunk_start(). */ PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); + png_const_bytep data, size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); @@ -1044,7 +1009,7 @@ PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), * the API will be removed in the future. */ PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); + size_t png_info_struct_size), PNG_DEPRECATED); /* Writes all the PNG information before the image. */ PNG_EXPORT(20, void, png_write_info_before_PLTE, @@ -1141,7 +1106,7 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, * corresponding composited pixel, and the color channels are unassociated * (not premultiplied). The gamma encoded color channels must be scaled * according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode + * the encoding, scale the color values, perform the composition and re-encode * the values. This is the 'PNG' mode. * * The alternative is to 'associate' the alpha with the color information by @@ -1197,7 +1162,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how + * display preceded by a power-law lookup table of power 1.45. This is how * early Mac systems behaved. * * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1244,7 +1209,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * When the default gamma of PNG files doesn't match the output gamma. * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the + * you to provide a default gamma, but it also sets the output gamma to the * matching value. If you know your PNG files have a gamma that doesn't * match the output you can take advantage of the fact that * png_set_alpha_mode always sets the output gamma but only sets the PNG @@ -1695,7 +1660,7 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); * chunk will cause an error at this point unless it is to be saved. * positive: The chunk was handled, libpng will ignore/discard it. * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about * how this behavior will change in libpng 1.7 */ PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, @@ -1720,7 +1685,7 @@ PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, /* Function to be called when data becomes available */ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); /* A function which may be called *only* within png_process_data to stop the * processing of any more data. The function returns the number of bytes @@ -1729,7 +1694,7 @@ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, * 'save' is set to true the routine will first save all the pending data and * will always return 0. */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); /* A function which may be called *only* outside (after) a call to * png_process_data. It returns the number of bytes of data to skip in the @@ -1793,7 +1758,8 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, #define PNG_FREE_PLTE 0x1000U #define PNG_FREE_TRNS 0x2000U #define PNG_FREE_TEXT 0x4000U -#define PNG_FREE_ALL 0x7fffU +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU #define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED @@ -1873,7 +1839,7 @@ PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, png_const_inforp info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -2012,6 +1978,18 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, png_fixed_point int_blue_Z)) #endif +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + #ifdef PNG_gAMA_SUPPORTED PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, png_const_inforp info_ptr, double *file_gamma)) @@ -2030,9 +2008,6 @@ PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, #ifdef PNG_hIST_SUPPORTED PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, png_inforp info_ptr, png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, png_inforp info_ptr, png_const_uint_16p hist)); #endif @@ -2233,7 +2208,7 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks * it simply resets the behavior to the libpng default. * - * INTERACTION WTIH USER CHUNK CALLBACKS: + * INTERACTION WITH USER CHUNK CALLBACKS: * The per-chunk handling is always used when there is a png_user_chunk_ptr * callback and the callback returns 0; the chunk is then always stored *unless* * it is critical and the per-chunk setting is other than ALWAYS. Notice that @@ -2300,8 +2275,10 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to * be processed by libpng. */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ /* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; * the result is therefore true (non-zero) if special handling is required, @@ -2309,7 +2286,7 @@ PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, */ PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, png_const_bytep chunk_name)); -#endif +#endif /* SET_UNKNOWN_CHUNKS */ #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, @@ -2530,33 +2507,37 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + 128); \ - (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); } +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(65535 \ - - (png_uint_32)(alpha)) + 32768); \ - (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); } +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } #else /* Standard method using integer division */ -# define png_composite(composite, fg, alpha, bg) \ - (composite) = \ - (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - 127) / 255)) +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = \ - (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ - 32767) / 65535)) +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) #endif /* READ_COMPOSITE_NODIV */ #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED @@ -2592,38 +2573,38 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); * format for negative values, which is almost certainly true. */ # define PNG_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the * function) incorrectly returned a value of type png_uint_32. */ # define PNG_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) # define PNG_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ - : (png_int_32)png_get_uint_32(buf))) + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) - /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, - * but defining a macro name prefixed with PNG_PREFIX. - */ +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ # ifndef PNG_PREFIX -# define png_get_uint_32(buf) PNG_get_uint_32(buf) -# define png_get_uint_16(buf) PNG_get_uint_16(buf) -# define png_get_int_32(buf) PNG_get_int_32(buf) +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) # endif #else # ifdef PNG_PREFIX - /* No macros; revert to the (redefined) function */ -# define PNG_get_uint_32 (png_get_uint_32) -# define PNG_get_uint_16 (png_get_uint_16) -# define PNG_get_int_32 (png_get_int_32) + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) # endif #endif @@ -2646,7 +2627,7 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, * The simplified API hides the details of both libpng and the PNG file format * itself. It allows PNG files to be read into a very limited number of * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more + * formats do not accommodate your needs then you can, and should, use the more * sophisticated APIs above - these support a wide variety of in-memory formats * and a wide variety of sophisticated transformations to those formats as well * as a wide variety of APIs to manipulate ancillary information. @@ -2752,7 +2733,7 @@ typedef struct * * When the simplified API needs to convert between sRGB and linear colorspaces, * the actual sRGB transfer curve defined in the sRGB specification (see the - * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 + * article at ) is used, not the gamma=1/2.2 * approximation used elsewhere in libpng. * * When an alpha channel is present it is expected to denote pixel coverage @@ -2807,6 +2788,8 @@ typedef struct # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ #endif +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + /* Commonly used formats have predefined macros. * * First the single byte (sRGB) formats: @@ -2953,7 +2936,7 @@ typedef struct * 'flags' field of png_image. */ #define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 - /* This indicates the the RGB values of the in-memory bitmap do not + /* This indicates that the RGB values of the in-memory bitmap do not * correspond to the red, green and blue end-points defined by sRGB. */ @@ -3006,7 +2989,7 @@ PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, #endif /* STDIO */ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); + png_const_voidp memory, size_t size)); /* The PNG header is read from the given memory buffer. */ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, @@ -3119,7 +3102,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * than or equal to the original value. * * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if + * occurred during write. If *memory_bytes was changed, or is not 0 if * 'memory' was NULL, the write would have succeeded but for the memory * buffer being too small. *memory_bytes contains the required number of * bytes and will be bigger that the original value. @@ -3171,9 +3154,9 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, #define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ - 12U+3U*(image).colormap_entries/*PLTE data*/+\ - (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ - 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) /* A helper for the following macro; if your compiler cannot handle the * following macro use this one with the result of @@ -3203,7 +3186,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * by the PNG_OPTION_ defines below. * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, * are detected at run time, however sometimes it may be impossible * to do this in user mode, in which case it is necessary to discover * the capabilities in an OS specific way. Such capabilities are @@ -3221,7 +3204,14 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, #endif #define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ #define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ -#define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ /* Return values: NOTE: there are four values and 'off' is *not* zero */ #define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ @@ -3245,7 +3235,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, * one to use is one more than this.) */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(245); + PNG_EXPORT_LAST_ORDINAL(249); #endif #ifdef __cplusplus diff --git a/source/Irrlicht/libpng/pngconf.h b/source/Irrlicht/libpng/pngconf.h index 058bcf67..dcba9f9d 100644 --- a/source/Irrlicht/libpng/pngconf.h +++ b/source/Irrlicht/libpng/pngconf.h @@ -1,11 +1,12 @@ -/* pngconf.h - machine configurable file for libpng +/* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.23, June 9, 2016 + * libpng version 1.6.37 * - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -57,14 +58,13 @@ #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. +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. */ #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 +/* 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. @@ -127,7 +127,7 @@ * * 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 + * (x86 DOS/Windows systems) 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 @@ -188,27 +188,27 @@ * 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! - */ + /* 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'. - */ + /* 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. - */ + /* 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 @@ -225,10 +225,10 @@ # 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. - */ + /* 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 @@ -244,9 +244,9 @@ # 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!) - */ + /* 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 */ @@ -267,7 +267,7 @@ */ #ifndef PNG_IMPEXP # if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ + /* This forces use of a DLL, disallowing static linking */ # define PNG_IMPEXP PNG_DLL_IMPORT # endif @@ -340,7 +340,7 @@ * less efficient code. */ # if defined(__clang__) && defined(__has_attribute) - /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ + /* 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 @@ -507,16 +507,18 @@ # error "libpng requires a signed 32-bit (or more) type" #endif -#if UINT_MAX > 4294967294 +#if UINT_MAX > 4294967294U typedef unsigned int png_uint_32; -#elif ULONG_MAX > 4294967294 +#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. +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. */ typedef size_t png_size_t; typedef ptrdiff_t png_ptrdiff_t; @@ -537,13 +539,12 @@ typedef ptrdiff_t png_ptrdiff_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. +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from 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 + * Casts in the other direction (from png_alloc_size_t to size_t or * png_uint_32) should be explicitly applied; however, we do not expect to * encounter practical situations that require such conversions. * @@ -553,7 +554,7 @@ typedef ptrdiff_t png_ptrdiff_t; #ifdef PNG_SMALL_SIZE_T typedef png_uint_32 png_alloc_size_t; #else - typedef png_size_t png_alloc_size_t; + typedef size_t png_alloc_size_t; #endif /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler @@ -589,8 +590,8 @@ 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; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; #ifdef PNG_STDIO_SUPPORTED typedef FILE * png_FILE_p; diff --git a/source/Irrlicht/libpng/pngdebug.h b/source/Irrlicht/libpng/pngdebug.h index 3d1e78c1..5530c0c9 100644 --- a/source/Irrlicht/libpng/pngdebug.h +++ b/source/Irrlicht/libpng/pngdebug.h @@ -1,10 +1,10 @@ /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c * - * Last changed in libpng 1.6.8 [December 19, 2013] + * Copyright (c) 2018 Cosmin Truta * 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.) + * Copyright (c) 1996-1997 Andreas Dilger + * 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 diff --git a/source/Irrlicht/libpng/pngerror.c b/source/Irrlicht/libpng/pngerror.c index 3e5f33f7..c612e7a9 100644 --- a/source/Irrlicht/libpng/pngerror.c +++ b/source/Irrlicht/libpng/pngerror.c @@ -1,10 +1,10 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2002,2004,2006-2014 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -26,7 +26,7 @@ static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); + png_const_charp warning_message)); #endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function @@ -37,7 +37,7 @@ png_default_warning PNGARG((png_const_structrp png_ptr, #ifdef PNG_ERROR_TEXT_SUPPORTED PNG_FUNCTION(void,PNGAPI png_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { #ifdef PNG_ERROR_NUMBERS_SUPPORTED char msg[16]; @@ -65,18 +65,18 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message), else error_message += offset; - } - - else - { - if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) - { - msg[0] = '0'; - msg[1] = '\0'; - error_message = msg; } - } - } + + 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) @@ -110,7 +110,7 @@ png_err,(png_const_structrp png_ptr),PNG_NORETURN) */ size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string) + png_const_charp string) { if (buffer != NULL && pos < bufsize) { @@ -131,7 +131,7 @@ png_safecat(png_charp buffer, size_t bufsize, size_t pos, */ png_charp png_format_number(png_const_charp start, png_charp end, int format, - png_alloc_size_t number) + png_alloc_size_t number) { int count = 0; /* number of digits output */ int mincount = 1; /* minimum number required */ @@ -163,7 +163,7 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_02u: /* Expects at least 2 digits. */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_u: *--end = digits[number % 10]; @@ -173,7 +173,7 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_02x: /* This format expects at least two digits */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_x: *--end = digits[number & 0xf]; @@ -233,7 +233,7 @@ png_warning(png_const_structrp png_ptr, png_const_charp warning_message) } if (png_ptr != NULL && png_ptr->warning_fn != NULL) (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), - warning_message + offset); + warning_message + offset); else png_default_warning(png_ptr, warning_message + offset); } @@ -245,7 +245,7 @@ png_warning(png_const_structrp png_ptr, png_const_charp warning_message) */ void png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string) + png_const_charp string) { if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); @@ -253,7 +253,7 @@ png_warning_parameter(png_warning_parameters p, int number, void png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, - png_alloc_size_t value) + png_alloc_size_t value) { char buffer[PNG_NUMBER_BUFFER_SIZE]; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); @@ -261,7 +261,7 @@ png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, void png_warning_parameter_signed(png_warning_parameters p, int number, int format, - png_int_32 value) + png_int_32 value) { png_alloc_size_t u; png_charp str; @@ -282,7 +282,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, void png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, - png_const_charp message) + 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 @@ -391,10 +391,10 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) 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); + 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) @@ -404,10 +404,10 @@ png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) 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); + 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) @@ -425,7 +425,7 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message) * if the character is invalid. */ #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { +static const char png_digit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -478,7 +478,7 @@ png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp #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) + PNG_NORETURN) { char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) @@ -573,7 +573,7 @@ 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) - int iin; + unsigned int iin; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; memcpy(msg, fixed_message, fixed_message_ln); iin = 0; @@ -620,7 +620,7 @@ png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, else { png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, - png_malloc_warn(png_ptr, jmp_buf_size)); + png_malloc_warn(png_ptr, jmp_buf_size)); if (png_ptr->jmp_buf_ptr == NULL) return NULL; /* new NULL return on OOM */ @@ -709,7 +709,7 @@ png_free_jmpbuf(png_structrp png_ptr) */ static PNG_FUNCTION(void /* PRIVATE */, png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { #ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_ERROR_NUMBERS_SUPPORTED @@ -883,9 +883,9 @@ png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) */ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), - PNG_NORETURN) + PNG_NORETURN) { - const png_const_structrp png_ptr = png_nonconst_ptr; + 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) @@ -906,7 +906,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), /* Missing longjmp buffer, the following is to help debugging: */ { size_t pos = png_safecat(image->message, (sizeof image->message), 0, - "bad longjmp: "); + "bad longjmp: "); png_safecat(image->message, (sizeof image->message), pos, error_message); } @@ -920,7 +920,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), 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_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. */ diff --git a/source/Irrlicht/libpng/pngget.c b/source/Irrlicht/libpng/pngget.c index 53a06ff1..e7348645 100644 --- a/source/Irrlicht/libpng/pngget.c +++ b/source/Irrlicht/libpng/pngget.c @@ -1,10 +1,10 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -26,7 +26,7 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, return(0); } -png_size_t PNGAPI +size_t PNGAPI png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) @@ -338,7 +338,7 @@ ppi_from_ppm(png_uint_32 ppm) png_fixed_point result; if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, 5000) != 0) - return result; + return (png_uint_32)result; /* Overflow. */ return 0; @@ -367,7 +367,7 @@ png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) static png_fixed_point png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) { - /* Convert from metres * 1,000,000 to inches * 100,000, meters to + /* Convert from meters * 1,000,000 to inches * 100,000, meters to * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. * Notice that this can overflow - a warning is output and 0 is * returned. @@ -486,7 +486,7 @@ png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) #ifdef PNG_bKGD_SUPPORTED png_uint_32 PNGAPI png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_16p *background) + png_color_16p *background) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0 && @@ -526,28 +526,28 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, if (white_x != NULL) *white_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); + info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); if (white_y != NULL) *white_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); + info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); if (red_x != NULL) *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, - "cHRM red X"); + "cHRM red X"); if (red_y != NULL) *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, - "cHRM red Y"); + "cHRM red Y"); if (green_x != NULL) *green_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); + info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); if (green_y != NULL) *green_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); + info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); if (blue_x != NULL) *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, - "cHRM blue X"); + "cHRM blue X"); if (blue_y != NULL) *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, - "cHRM blue Y"); + "cHRM blue Y"); return (PNG_INFO_cHRM); } @@ -556,42 +556,42 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 PNGAPI png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *red_X, double *red_Y, double *red_Z, double *green_X, - double *green_Y, double *green_Z, double *blue_X, double *blue_Y, - double *blue_Z) + double *red_X, double *red_Y, double *red_Z, double *green_X, + double *green_Y, double *green_Z, double *blue_X, double *blue_Y, + double *blue_Z) { if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); if (red_X != NULL) *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, - "cHRM red X"); + "cHRM red X"); if (red_Y != NULL) *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, - "cHRM red Y"); + "cHRM red Y"); if (red_Z != NULL) *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, - "cHRM red Z"); + "cHRM red Z"); if (green_X != NULL) *green_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); + info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); if (green_Y != NULL) *green_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); + info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); if (green_Z != NULL) *green_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); + info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); if (blue_X != NULL) *blue_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); + info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); if (blue_Y != NULL) *blue_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); + info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); if (blue_Z != NULL) *blue_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); + info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); return (PNG_INFO_cHRM); } @@ -681,8 +681,8 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, png_debug1(1, "in %s retrieval function", "gAMA"); if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - file_gamma != NULL) + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && + file_gamma != NULL) { *file_gamma = info_ptr->colorspace.gamma; return (PNG_INFO_gAMA); @@ -704,7 +704,7 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, file_gamma != NULL) { *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, - "png_get_gAMA"); + "png_get_gAMA"); return (PNG_INFO_gAMA); } @@ -741,8 +741,7 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) != 0 && - name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) + name != NULL && profile != NULL && proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; @@ -750,11 +749,13 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, /* This is somewhat irrelevant since the profile data returned has * actually been uncompressed. */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; + if (compression_type != NULL) + *compression_type = PNG_COMPRESSION_TYPE_BASE; return (PNG_INFO_iCCP); } return (0); + } #endif @@ -773,6 +774,35 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, } #endif +#ifdef PNG_eXIf_SUPPORTED +png_uint_32 PNGAPI +png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep *exif) +{ + png_warning(png_ptr, "png_get_eXIf does not work; use png_get_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(exif) + return 0; +} + +png_uint_32 PNGAPI +png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *num_exif, png_bytep *exif) +{ + png_debug1(1, "in %s retrieval function", "eXIf"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_eXIf) != 0 && exif != NULL) + { + *num_exif = info_ptr->num_exif; + *exif = info_ptr->exif; + return (PNG_INFO_eXIf); + } + + return (0); +} +#endif + #ifdef PNG_hIST_SUPPORTED png_uint_32 PNGAPI png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, @@ -901,7 +931,7 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, */ *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), - "sCAL height"); + "sCAL height"); return (PNG_INFO_sCAL); } @@ -1135,7 +1165,7 @@ png_get_user_chunk_ptr(png_const_structrp png_ptr) } #endif -png_size_t PNGAPI +size_t PNGAPI png_get_compression_buffer_size(png_const_structrp png_ptr) { if (png_ptr == NULL) diff --git a/source/Irrlicht/libpng/pnginfo.h b/source/Irrlicht/libpng/pnginfo.h index 036f58c2..dbbc35bc 100644 --- a/source/Irrlicht/libpng/pnginfo.h +++ b/source/Irrlicht/libpng/pnginfo.h @@ -1,10 +1,10 @@ /* 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -55,10 +55,10 @@ 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_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) */ + 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) */ @@ -185,6 +185,14 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) 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 @@ -239,7 +247,7 @@ defined(PNG_READ_BACKGROUND_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 + * values. The values are width and height corresponding to one pixel * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is * non-zero. */ diff --git a/source/Irrlicht/libpng/pnglibconf.h b/source/Irrlicht/libpng/pnglibconf.h index c5a5f803..11364203 100644 --- a/source/Irrlicht/libpng/pnglibconf.h +++ b/source/Irrlicht/libpng/pnglibconf.h @@ -1,213 +1,219 @@ -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.6.23, June 9, 2016 */ - -/* Copyright (c) 1998-2016 Glenn Randers-Pehrson */ - -/* This code is released under the libpng license. */ -/* For conditions of distribution and use, see the disclaimer */ -/* and license in png.h */ - -/* pnglibconf.h */ -/* Machine generated file: DO NOT EDIT */ -/* Derived from: scripts/pnglibconf.dfa */ -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGNED_MEMORY_SUPPORTED -/*#undef PNG_ARM_NEON_API_SUPPORTED*/ -/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_BENIGN_READ_ERRORS_SUPPORTED -/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ -#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_COLORSPACE_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_FORMAT_AFIRST_SUPPORTED -#define PNG_FORMAT_BGR_SUPPORTED -#define PNG_GAMMA_SUPPORTED -#define PNG_GET_PALETTE_MAX_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_ALPHA_MODE_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_COMPRESSED_TEXT_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GET_PALETTE_MAX_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_SCALE_16_TO_8_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_OPTION_SUPPORTED -#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED -#define PNG_SIMPLIFIED_READ_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_zTXt_SUPPORTED -/* end of options */ -/* settings */ -#define PNG_API_RULE 0 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE -#define PNG_INFLATE_BUF_SIZE 1024 -#define PNG_LINKAGE_API extern -#define PNG_LINKAGE_CALLBACK extern -#define PNG_LINKAGE_DATA extern -#define PNG_LINKAGE_FUNCTION extern -#define PNG_MAX_GAMMA_8 11 -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) -#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 -#define PNG_USER_CHUNK_CACHE_MAX 1000 -#define PNG_USER_CHUNK_MALLOC_MAX 8000000 -#define PNG_USER_HEIGHT_MAX 1000000 -#define PNG_USER_WIDTH_MAX 1000000 -#define PNG_ZBUF_SIZE 8192 -#define PNG_ZLIB_VERNUM 0x1280 -#define PNG_Z_DEFAULT_COMPRESSION (-1) -#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 -#define PNG_Z_DEFAULT_STRATEGY 1 -#define PNG_sCAL_PRECISION 5 -#define PNG_sRGB_PROFILE_CHECKS 2 -/* end of settings */ -#endif /* PNGLCONF_H */ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.37 */ + +/* Copyright (c) 2018-2019 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0 /* unknown */ +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/source/Irrlicht/libpng/pngmem.c b/source/Irrlicht/libpng/pngmem.c index 52028fb2..5780e764 100644 --- a/source/Irrlicht/libpng/pngmem.c +++ b/source/Irrlicht/libpng/pngmem.c @@ -1,10 +1,10 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2002,2004,2006-2014 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -66,7 +66,7 @@ png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) */ PNG_FUNCTION(png_voidp /* PRIVATE */, png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) + 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 @@ -107,9 +107,9 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), */ static png_voidp png_malloc_array_checked(png_const_structrp png_ptr, int nelements, - size_t element_size) + size_t element_size) { - png_alloc_size_t req = nelements; /* known to be > 0 */ + 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); @@ -120,7 +120,7 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements, PNG_FUNCTION(png_voidp /* PRIVATE */, png_malloc_array,(png_const_structrp png_ptr, int nelements, - size_t element_size),PNG_ALLOCATED) + size_t element_size),PNG_ALLOCATED) { if (nelements <= 0 || element_size == 0) png_error(png_ptr, "internal error: array alloc"); @@ -130,7 +130,7 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements, 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) + 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 || @@ -143,7 +143,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, if (add_elements <= INT_MAX - old_elements) { png_voidp new_array = png_malloc_array_checked(png_ptr, - old_elements+add_elements, element_size); + old_elements+add_elements, element_size); if (new_array != NULL) { @@ -154,7 +154,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, 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); + element_size*(unsigned)add_elements); return new_array; } @@ -187,7 +187,7 @@ png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) #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_ALLOCATED PNG_DEPRECATED) { png_voidp ret; @@ -210,7 +210,7 @@ png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), */ PNG_FUNCTION(png_voidp,PNGAPI png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) + PNG_ALLOCATED) { if (png_ptr != NULL) { diff --git a/source/Irrlicht/libpng/pngpread.c b/source/Irrlicht/libpng/pngpread.c index 23dce14b..b2306c07 100644 --- a/source/Irrlicht/libpng/pngpread.c +++ b/source/Irrlicht/libpng/pngpread.c @@ -1,10 +1,10 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.23 [June 9, 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -34,7 +34,7 @@ if (png_ptr->buffer_size < N) \ void PNGAPI png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) + png_bytep buffer, size_t buffer_size) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -47,7 +47,7 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr, } } -png_size_t PNGAPI +size_t PNGAPI png_process_data_pause(png_structrp png_ptr, int save) { if (png_ptr != NULL) @@ -60,7 +60,7 @@ png_process_data_pause(png_structrp png_ptr, int save) else { /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; + size_t remaining = png_ptr->buffer_size; png_ptr->buffer_size = 0; /* So subtract the saved buffer size, unless all the data @@ -77,11 +77,11 @@ png_process_data_pause(png_structrp png_ptr, int save) png_uint_32 PNGAPI png_process_data_skip(png_structrp png_ptr) { - /* TODO: Deprecate and remove this API. - * Somewhere the implementation of this seems to have been lost, - * or abandoned. It was only to support some internal back-door access - * to png_struct) in libpng-1.4.x. - */ +/* TODO: Deprecate and remove this API. + * Somewhere the implementation of this seems to have been lost, + * or abandoned. It was only to support some internal back-door access + * to png_struct) in libpng-1.4.x. + */ png_app_warning(png_ptr, "png_process_data_skip is not implemented in any current version of libpng"); return 0; @@ -133,8 +133,8 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */ + size_t num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -189,6 +189,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_crc_read(png_ptr, chunk_tag, 4); png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_check_chunk_length(png_ptr, png_ptr->push_length); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } @@ -410,14 +411,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) { PNG_PUSH_SAVE_BUFFER_IF_FULL png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; } void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length) { png_bytep ptr; @@ -427,7 +428,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) ptr = buffer; if (png_ptr->save_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->save_buffer_size) save_size = length; @@ -444,7 +445,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) } if (length != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->current_buffer_size) save_size = length; @@ -466,7 +467,7 @@ png_push_save_buffer(png_structrp png_ptr) { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i, istop; + size_t i, istop; png_bytep sp; png_bytep dp; @@ -481,7 +482,7 @@ png_push_save_buffer(png_structrp png_ptr) if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > png_ptr->save_buffer_max) { - png_size_t new_max; + size_t new_max; png_bytep old_buffer; if (png_ptr->save_buffer_size > PNG_SIZE_MAX - @@ -493,7 +494,7 @@ png_push_save_buffer(png_structrp png_ptr) new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; old_buffer = png_ptr->save_buffer; png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); + (size_t)new_max); if (png_ptr->save_buffer == NULL) { @@ -521,7 +522,7 @@ png_push_save_buffer(png_structrp png_ptr) void /* PRIVATE */ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -561,7 +562,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) { - png_size_t save_size = png_ptr->save_buffer_size; + size_t save_size = png_ptr->save_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -571,7 +572,7 @@ png_push_read_IDAT(png_structrp png_ptr) * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -588,7 +589,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size = png_ptr->current_buffer_size; + size_t save_size = png_ptr->current_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -597,7 +598,7 @@ png_push_read_IDAT(png_structrp png_ptr) * larger - this cannot overflow. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -624,7 +625,7 @@ png_push_read_IDAT(png_structrp png_ptr) void /* PRIVATE */ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL) @@ -684,7 +685,12 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, png_warning(png_ptr, "Truncated compressed data in IDAT"); else - png_error(png_ptr, "Decompression error in IDAT"); + { + if (ret == Z_DATA_ERROR) + png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch"); + else + png_error(png_ptr, "Decompression error in IDAT"); + } /* Skip the check on unprocessed input */ return; @@ -782,7 +788,7 @@ png_push_process_row(png_structrp png_ptr) { if (png_ptr->pass < 6) png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); + png_ptr->transformations); switch (png_ptr->pass) { @@ -966,20 +972,20 @@ png_read_push_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; /* Height of interlace block. This is not currently used - if you need * it, uncomment it here and in png.h - static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; */ #endif @@ -1044,7 +1050,7 @@ png_push_have_row(png_structrp png_ptr, png_bytep row) { if (png_ptr->row_fn != NULL) (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); + (int)png_ptr->pass); } #ifdef PNG_READ_INTERLACING_SUPPORTED diff --git a/source/Irrlicht/libpng/pngpriv.h b/source/Irrlicht/libpng/pngpriv.h index e2ad960d..7018f3db 100644 --- a/source/Irrlicht/libpng/pngpriv.h +++ b/source/Irrlicht/libpng/pngpriv.h @@ -1,10 +1,10 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.22 [May 26, 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -35,7 +35,9 @@ * Windows/Visual Studio) there is no effect; the OS specific tests below are * still required (as of 2011-05-02.) */ -#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#endif #ifndef PNG_VERSION_INFO_ONLY /* Standard library headers not required by png.h: */ @@ -172,7 +174,10 @@ # else /* !defined __ARM_NEON__ */ /* The 'intrinsics' code simply won't compile without this -mfpu=neon: */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 +# if !defined(__aarch64__) + /* The assembler code currently does not work on ARM64 */ +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* __aarch64__ */ # endif /* __ARM_NEON__ */ # endif /* !PNG_ARM_NEON_IMPLEMENTATION */ @@ -182,6 +187,90 @@ # endif #endif /* PNG_ARM_NEON_OPT > 0 */ +#ifndef PNG_MIPS_MSA_OPT +# if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_MIPS_MSA_OPT 2 +# else +# define PNG_MIPS_MSA_OPT 0 +# endif +#endif + +#ifndef PNG_POWERPC_VSX_OPT +# if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) +# define PNG_POWERPC_VSX_OPT 2 +# else +# define PNG_POWERPC_VSX_OPT 0 +# endif +#endif + +#ifndef PNG_INTEL_SSE_OPT +# ifdef PNG_INTEL_SSE + /* Only check for SSE if the build configuration has been modified to + * enable SSE optimizations. This means that these optimizations will + * be off by default. See contrib/intel for more details. + */ +# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ + defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_OPT 1 +# else +# define PNG_INTEL_SSE_OPT 0 +# endif +# else +# define PNG_INTEL_SSE_OPT 0 +# endif +#endif + +#if PNG_INTEL_SSE_OPT > 0 +# ifndef PNG_INTEL_SSE_IMPLEMENTATION +# if defined(__SSE4_1__) || defined(__AVX__) + /* We are not actually using AVX, but checking for AVX is the best + way we can detect SSE4.1 and SSSE3 on MSVC. + */ +# define PNG_INTEL_SSE_IMPLEMENTATION 3 +# elif defined(__SSSE3__) +# define PNG_INTEL_SSE_IMPLEMENTATION 2 +# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2) +# define PNG_INTEL_SSE_IMPLEMENTATION 1 +# else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +# endif +# endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 +# endif +#else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 +#endif + +#if PNG_MIPS_MSA_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa +# ifndef PNG_MIPS_MSA_IMPLEMENTATION +# if defined(__mips_msa) +# if defined(__clang__) +# elif defined(__GNUC__) +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) +# define PNG_MIPS_MSA_IMPLEMENTATION 2 +# endif /* no GNUC support */ +# endif /* __GNUC__ */ +# else /* !defined __mips_msa */ +# define PNG_MIPS_MSA_IMPLEMENTATION 2 +# endif /* __mips_msa */ +# endif /* !PNG_MIPS_MSA_IMPLEMENTATION */ + +# ifndef PNG_MIPS_MSA_IMPLEMENTATION +# define PNG_MIPS_MSA_IMPLEMENTATION 1 +# endif +#endif /* PNG_MIPS_MSA_OPT > 0 */ + +#if PNG_POWERPC_VSX_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx +# define PNG_POWERPC_VSX_IMPLEMENTATION 1 +#endif + + /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If * so PNG_BUILD_DLL must be set. @@ -374,25 +463,6 @@ # define png_fixed_error(s1,s2) png_err(s1) #endif -/* C allows up-casts from (void*) to any pointer and (const void*) to any - * pointer to a const object. C++ regards this as a type error and requires an - * explicit, static, cast and provides the static_cast<> rune to ensure that - * const is not cast away. - */ -#ifdef __cplusplus -# define png_voidcast(type, value) static_cast(value) -# define png_constcast(type, value) const_cast(value) -# define png_aligncast(type, value) \ - static_cast(static_cast(value)) -# define png_aligncastconst(type, value) \ - static_cast(static_cast(value)) -#else -# define png_voidcast(type, value) (value) -# define png_constcast(type, value) ((type)(value)) -# define png_aligncast(type, value) ((void*)(value)) -# define png_aligncastconst(type, value) ((const void*)(value)) -#endif /* __cplusplus */ - /* Some fixed point APIs are still required even if not exported because * they get used by the corresponding floating point APIs. This magic * deals with this: @@ -407,6 +477,35 @@ /* Other defines specific to compilers can go here. Try to keep * them inside an appropriate ifdef/endif pair for portability. */ + +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +# define png_constcast(type, value) const_cast(value) +# define png_aligncast(type, value) \ + static_cast(static_cast(value)) +# define png_aligncastconst(type, value) \ + static_cast(static_cast(value)) +#else +# define png_voidcast(type, value) (value) +# ifdef _WIN64 +# ifdef __GNUC__ + typedef unsigned long long png_ptruint; +# else + typedef unsigned __int64 png_ptruint; +# endif +# else + typedef unsigned long png_ptruint; +# endif +# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value)) +# define png_aligncast(type, value) ((void*)(value)) +# define png_aligncastconst(type, value) ((const void*)(value)) +#endif /* __cplusplus */ + #if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) /* png.c requires the following ANSI-C constants if the conversion of @@ -420,10 +519,10 @@ # if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ # if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) # include # endif @@ -431,9 +530,9 @@ # include # endif # if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ # include # endif #endif @@ -504,7 +603,8 @@ /* This implicitly assumes alignment is always to a power of 2. */ #ifdef png_alignof # define png_isaligned(ptr, type)\ - ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) + (((type)((const char*)ptr-(const char*)0) & \ + (type)(png_alignof(type)-1)) == 0) #else # define png_isaligned(ptr, type) 0 #endif @@ -521,92 +621,92 @@ * are defined in png.h because they need to be visible to applications * that call png_set_unknown_chunk(). */ -/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ -/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ -#define PNG_HAVE_IDAT 0x04 -/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ -#define PNG_HAVE_IEND 0x10 - /* 0x20 (unused) */ - /* 0x40 (unused) */ - /* 0x80 (unused) */ -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - /* 0x4000 (unused) */ -#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ +/* #define PNG_HAVE_IHDR 0x01U (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02U (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04U +/* #define PNG_AFTER_IDAT 0x08U (defined in png.h) */ +#define PNG_HAVE_IEND 0x10U + /* 0x20U (unused) */ + /* 0x40U (unused) */ + /* 0x80U (unused) */ +#define PNG_HAVE_CHUNK_HEADER 0x100U +#define PNG_WROTE_tIME 0x200U +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400U +#define PNG_BACKGROUND_IS_GRAY 0x800U +#define PNG_HAVE_PNG_SIGNATURE 0x1000U +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ + /* 0x4000U (unused) */ +#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ /* Flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_QUANTIZE 0x0040 -#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ -#define PNG_BACKGROUND_EXPAND 0x0100 -#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ -#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000 -#define PNG_PACKSWAP 0x10000 -#define PNG_SWAP_ALPHA 0x20000 -#define PNG_STRIP_ALPHA 0x40000 -#define PNG_INVERT_ALPHA 0x80000 -#define PNG_USER_TRANSFORM 0x100000 -#define PNG_RGB_TO_GRAY_ERR 0x200000 -#define PNG_RGB_TO_GRAY_WARN 0x400000 -#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ -#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ -#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ -#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ +#define PNG_BGR 0x0001U +#define PNG_INTERLACE 0x0002U +#define PNG_PACK 0x0004U +#define PNG_SHIFT 0x0008U +#define PNG_SWAP_BYTES 0x0010U +#define PNG_INVERT_MONO 0x0020U +#define PNG_QUANTIZE 0x0040U +#define PNG_COMPOSE 0x0080U /* Was PNG_BACKGROUND */ +#define PNG_BACKGROUND_EXPAND 0x0100U +#define PNG_EXPAND_16 0x0200U /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400U /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800U +#define PNG_EXPAND 0x1000U +#define PNG_GAMMA 0x2000U +#define PNG_GRAY_TO_RGB 0x4000U +#define PNG_FILLER 0x8000U +#define PNG_PACKSWAP 0x10000U +#define PNG_SWAP_ALPHA 0x20000U +#define PNG_STRIP_ALPHA 0x40000U +#define PNG_INVERT_ALPHA 0x80000U +#define PNG_USER_TRANSFORM 0x100000U +#define PNG_RGB_TO_GRAY_ERR 0x200000U +#define PNG_RGB_TO_GRAY_WARN 0x400000U +#define PNG_RGB_TO_GRAY 0x600000U /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000U /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000U /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000U /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000U /* Added to libpng-1.5.4 */ + /* 0x8000000U unused */ + /* 0x10000000U unused */ + /* 0x20000000U unused */ + /* 0x40000000U unused */ /* Flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 +#define PNG_STRUCT_PNG 0x0001U +#define PNG_STRUCT_INFO 0x0002U /* Flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ - /* 0x0004 unused */ -#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ - /* 0x0010 unused */ - /* 0x0020 unused */ -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ -/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ -/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ -#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ -#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ - /* 0x800000 unused */ - /* 0x1000000 unused */ - /* 0x2000000 unused */ - /* 0x4000000 unused */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001U +#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002U /* Added to libpng-1.6.0 */ + /* 0x0004U unused */ +#define PNG_FLAG_ZSTREAM_ENDED 0x0008U /* Added to libpng-1.6.0 */ + /* 0x0010U unused */ + /* 0x0020U unused */ +#define PNG_FLAG_ROW_INIT 0x0040U +#define PNG_FLAG_FILLER_AFTER 0x0080U +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100U +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200U +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400U +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800U +#define PNG_FLAG_ASSUME_sRGB 0x1000U /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000U /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000U /* Added to libpng-1.5.4 */ +/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000U */ +/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000U */ +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000U +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000U +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000U +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000U /* Added to libpng-1.4.0 */ +#define PNG_FLAG_APP_WARNINGS_WARN 0x200000U /* Added to libpng-1.6.0 */ +#define PNG_FLAG_APP_ERRORS_WARN 0x400000U /* Added to libpng-1.6.0 */ + /* 0x800000U unused */ + /* 0x1000000U unused */ + /* 0x2000000U unused */ + /* 0x4000000U unused */ + /* 0x8000000U unused */ + /* 0x10000000U unused */ + /* 0x20000000U unused */ + /* 0x40000000U unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) @@ -637,8 +737,26 @@ /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \ + (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) ) + +/* This returns the number of trailing bits in the last byte of a row, 0 if the + * last byte is completely full of pixels. It is, in principle, (pixel_bits x + * width) % 8, but that would overflow for large 'width'. The second macro is + * the same except that it returns the number of unused bits in the last byte; + * (8-TRAILBITS), but 0 when TRAILBITS is 0. + * + * NOTE: these macros are intended to be self-evidently correct and never + * overflow on the assumption that pixel_bits is in the range 0..255. The + * arguments are evaluated only once and they can be signed (e.g. as a result of + * the integral promotions). The result of the expression always has type + * (png_uint_32), however the compiler always knows it is in the range 0..7. + */ +#define PNG_TRAILBITS(pixel_bits, width) \ + (((pixel_bits) * ((width) % (png_uint_32)8)) % 8) + +#define PNG_PADBITS(pixel_bits, width) \ + ((8 - PNG_TRAILBITS(pixel_bits, width)) % 8) /* PNG_OUT_OF_RANGE returns true if value is outside the range * ideal-delta..ideal+delta. Each argument is evaluated twice. @@ -733,6 +851,7 @@ #define png_PLTE PNG_U32( 80, 76, 84, 69) #define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_gAMA PNG_U32(103, 65, 77, 65) #define png_gIFg PNG_U32(103, 73, 70, 103) @@ -807,7 +926,7 @@ * PNG files the -I directives must match. * * The most likely explanation is that you passed a -I in CFLAGS. This will - * not work; all the preprocessor directories and in particular all the -I + * not work; all the preprocessor directives and in particular all the -I * directives must be in CPPFLAGS. */ #endif @@ -936,15 +1055,15 @@ PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); */ PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); + png_bytep buffer, size_t length),PNG_EMPTY); #endif PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED @@ -958,7 +1077,7 @@ PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); /* Write the "data" buffer to whatever output you are using */ PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); + png_const_bytep data, size_t length),PNG_EMPTY); /* Read and check the PNG file signature */ PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, @@ -970,7 +1089,7 @@ PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), /* Read data from whatever input you are using into the "data" buffer */ PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, - png_size_t length),PNG_EMPTY); + size_t length),PNG_EMPTY); /* Read bytes into buf, and update png_ptr->crc */ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, @@ -988,7 +1107,7 @@ PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); * since this is the maximum buffer size we can specify. */ PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); + png_const_bytep ptr, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); @@ -1025,7 +1144,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, #ifdef PNG_WRITE_cHRM_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, const png_xy *xy), PNG_EMPTY); - /* The xy value must have been previously validated */ + /* The xy value must have been previously validated */ #endif #ifdef PNG_WRITE_sRGB_SUPPORTED @@ -1033,6 +1152,11 @@ PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, int intent),PNG_EMPTY); #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr, + png_bytep exif, int num_exif),PNG_EMPTY); +#endif + #ifdef PNG_WRITE_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, png_const_charp name, png_const_bytep profile), PNG_EMPTY); @@ -1066,7 +1190,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, /* Chunks that have keywords */ #ifdef PNG_WRITE_tEXt_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, - png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); + png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY); #endif #ifdef PNG_WRITE_zTXt_SUPPORTED @@ -1174,6 +1298,7 @@ PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); +#if PNG_ARM_NEON_OPT > 0 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop @@ -1188,6 +1313,56 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_MIPS_MSA_OPT > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_POWERPC_VSX_OPT > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif /* Choose the best filter to use and filter the row data */ PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, @@ -1215,7 +1390,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), /* Initialize the row buffers, etc. */ PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush), PNG_EMPTY); # define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush) @@ -1281,6 +1456,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif +#ifdef PNG_READ_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); @@ -1356,9 +1536,12 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif -PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, +PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr, + png_uint_32 chunk_length),PNG_EMPTY); + PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); /* This is the function that gets called for unknown chunks. The 'keep' @@ -1400,10 +1583,10 @@ PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, @@ -1413,7 +1596,7 @@ PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, - png_bytep row),PNG_EMPTY); + png_bytep row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, @@ -1452,13 +1635,13 @@ PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, png_inforp info_ptr), PNG_EMPTY); - /* Synchronize the info 'valid' flags with the colorspace */ + /* Synchronize the info 'valid' flags with the colorspace */ PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, png_inforp info_ptr), PNG_EMPTY); - /* Copy the png_struct colorspace to the info_struct and call the above to - * synchronize the flags. Checks for NULL info_ptr and does nothing. - */ + /* Copy the png_struct colorspace to the info_struct and call the above to + * synchronize the flags. Checks for NULL info_ptr and does nothing. + */ #endif /* Added at libpng version 1.4.0 */ @@ -1492,9 +1675,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, /* The 'name' is used for information only */ /* Routines for checking parts of an ICC profile. */ +#ifdef PNG_READ_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length), PNG_EMPTY); +#endif /* READ_iCCP */ PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, @@ -1671,13 +1856,13 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, double fp, unsigned int precision), + png_charp ascii, size_t size, double fp, unsigned int precision), PNG_EMPTY); #endif /* FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); + png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY); #endif /* FIXED_POINT */ #endif /* sCAL */ @@ -1770,7 +1955,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * the problem character.) This has not been tested within libpng. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); /* This is the same but it checks a complete string and returns true * only if it just contains a floating point number. As of 1.5.4 this @@ -1779,7 +1964,7 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, * for negative or zero values using the sticky flag. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); + size_t size),PNG_EMPTY); #endif /* pCAL || sCAL */ #if defined(PNG_GAMMA_SUPPORTED) ||\ @@ -1854,7 +2039,7 @@ typedef struct png_control png_voidp error_buf; /* Always a jmp_buf at present. */ png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ + size_t size; /* Size of the memory buffer. */ unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int owned_file :1; /* We own the file in io_ptr */ @@ -1913,13 +2098,48 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. */ +# if PNG_ARM_NEON_OPT > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif +#if PNG_MIPS_MSA_OPT > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +#endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +# endif +#endif + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, png_const_charp key, png_bytep new_key), PNG_EMPTY); +#if PNG_ARM_NEON_IMPLEMENTATION == 1 +PNG_INTERNAL_FUNCTION(void, + png_riffle_palette_neon, + (png_structrp), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_rgba8_neon, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_rgb8_neon, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +#endif + /* Maintainer: Put new private prototypes here ^ */ #include "pngdebug.h" diff --git a/source/Irrlicht/libpng/pngread.c b/source/Irrlicht/libpng/pngread.c index 41c9e772..de5a3a7f 100644 --- a/source/Irrlicht/libpng/pngread.c +++ b/source/Irrlicht/libpng/pngread.c @@ -1,10 +1,10 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.23 [June 9, 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -28,10 +28,10 @@ png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, { #ifndef PNG_USER_MEM_SUPPORTED png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, NULL, NULL, NULL); + error_fn, warn_fn, NULL, NULL, NULL); #else return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL); + warn_fn, NULL, NULL, NULL); } /* Alternate create PNG structure for reading, and allocate any memory @@ -43,7 +43,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) { png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); #endif /* USER_MEM */ if (png_ptr != NULL) @@ -175,6 +175,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -252,7 +257,7 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) else png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } } #endif /* SEQUENTIAL_READ */ @@ -279,7 +284,7 @@ png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) /* New in 1.6.0 this avoids the bug of doing the initializations twice */ else png_app_error(png_ptr, - "png_read_update_info/png_start_read_image: duplicate call"); + "png_read_update_info/png_start_read_image: duplicate call"); } } @@ -302,7 +307,7 @@ png_start_read_image(png_structrp png_ptr) /* New in 1.6.0 this avoids the bug of doing the initializations twice */ else png_app_error(png_ptr, - "png_start_read_image/png_read_update_info: duplicate call"); + "png_start_read_image/png_read_update_info: duplicate call"); } } #endif /* SEQUENTIAL_READ */ @@ -359,9 +364,9 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5); png_uint_32 red = (s0 + s1 + 65536) & 0xffff; png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; *(rp ) = (png_byte)((red >> 8) & 0xff); @@ -534,13 +539,14 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) png_error(png_ptr, "Invalid attempt to read row data"); /* Fill the row with IDAT data: */ + png_ptr->row_buf[0]=255; /* to force error if no data was found */ png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) { if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); + png_ptr->prev_row + 1, png_ptr->row_buf[0]); else png_error(png_ptr, "bad adaptive filter value"); } @@ -584,7 +590,7 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) { if (png_ptr->pass < 6) png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); + png_ptr->transformations); if (dsp_row != NULL) png_combine_row(png_ptr, dsp_row, 1/*display*/); @@ -719,7 +725,7 @@ png_read_image(png_structrp png_ptr, png_bytepp image) * but the caller should do it! */ png_warning(png_ptr, "Interlace handling should be turned on when " - "using png_read_image"); + "using png_read_image"); /* Make sure this is set correctly */ png_ptr->num_rows = png_ptr->height; } @@ -779,8 +785,8 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED /* Report invalid palette index; added at libng-1.5.10 */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Read palette index exceeding num_palette"); + png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Read palette index exceeding num_palette"); #endif do @@ -842,6 +848,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -919,7 +930,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) else png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + PNG_HANDLE_CHUNK_AS_DEFAULT); } while ((png_ptr->mode & PNG_HAVE_IEND) == 0); } #endif /* SEQUENTIAL_READ */ @@ -983,6 +994,12 @@ png_read_destroy(png_structrp png_ptr) png_ptr->chunk_list = NULL; #endif +#if defined(PNG_READ_EXPAND_SUPPORTED) && \ + defined(PNG_ARM_NEON_IMPLEMENTATION) + png_free(png_ptr, png_ptr->riffled_palette); + png_ptr->riffled_palette = NULL; +#endif + /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error * callbacks are still set at this point. They are required to complete the * destruction of the png_struct itself. @@ -1030,8 +1047,7 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) #ifdef PNG_INFO_IMAGE_SUPPORTED void PNGAPI png_read_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, - voidp params) + int transforms, voidp params) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -1307,7 +1323,7 @@ png_image_read_init(png_imagep image) if (info_ptr != NULL) { png_controlp control = png_voidcast(png_controlp, - png_malloc_warn(png_ptr, (sizeof *control))); + png_malloc_warn(png_ptr, (sizeof *control))); if (control != NULL) { @@ -1394,7 +1410,9 @@ png_image_read_header(png_voidp argument) png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; +#ifdef PNG_BENIGN_ERRORS_SUPPORTED png_set_benign_errors(png_ptr, 1/*warn*/); +#endif png_read_info(png_ptr, info_ptr); /* Do this the fast way; just read directly out of png_struct. */ @@ -1432,7 +1450,7 @@ png_image_read_header(png_voidp argument) break; case PNG_COLOR_TYPE_PALETTE: - cmap_entries = png_ptr->num_palette; + cmap_entries = (png_uint_32)png_ptr->num_palette; break; default: @@ -1470,12 +1488,12 @@ png_image_begin_read_from_stdio(png_imagep image, FILE* file) else return png_image_error(image, - "png_image_begin_read_from_stdio: invalid argument"); + "png_image_begin_read_from_stdio: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); return 0; } @@ -1508,19 +1526,19 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name) else return png_image_error(image, - "png_image_begin_read_from_file: invalid argument"); + "png_image_begin_read_from_file: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); return 0; } #endif /* STDIO */ static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need) { if (png_ptr != NULL) { @@ -1531,7 +1549,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) if (cp != NULL) { png_const_bytep memory = cp->memory; - png_size_t size = cp->size; + size_t size = cp->size; if (memory != NULL && size >= need) { @@ -1550,7 +1568,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) } int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1573,12 +1591,12 @@ int PNGAPI png_image_begin_read_from_memory(png_imagep image, else return png_image_error(image, - "png_image_begin_read_from_memory: invalid argument"); + "png_image_begin_read_from_memory: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); + "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); return 0; } @@ -1609,7 +1627,7 @@ png_image_skip_unused_chunks(png_structrp png_ptr) * errors (which are unfortunately quite common.) */ { - static PNG_CONST png_byte chunks_to_process[] = { + static const png_byte chunks_to_process[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ 103, 65, 77, 65, '\0', /* gAMA */ @@ -1624,12 +1642,12 @@ png_image_skip_unused_chunks(png_structrp png_ptr) * IHDR, PLTE, tRNS, IDAT, and IEND chunks. */ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, - NULL, -1); + NULL, -1); /* But do not ignore image data handling chunks */ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, - chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5); - } + chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5); + } } # define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) @@ -1696,7 +1714,7 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) #ifdef __GNUC__ default: png_error(display->image->opaque->png_ptr, - "unexpected encoding (internal error)"); + "unexpected encoding (internal error)"); #endif } @@ -1705,8 +1723,8 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) static png_uint_32 png_colormap_compose(png_image_read_control *display, - png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, - png_uint_32 background, int encoding) + png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, + png_uint_32 background, int encoding) { /* The file value is composed on the background, the background has the given * encoding and so does the result, the file is encoded with P_FILE and the @@ -1742,14 +1760,14 @@ png_colormap_compose(png_image_read_control *display, */ static void png_create_colormap_entry(png_image_read_control *display, - png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, - png_uint_32 alpha, int encoding) + png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, + png_uint_32 alpha, int encoding) { png_imagep image = display->image; - const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? - P_LINEAR : P_sRGB; - const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && - (red != green || green != blue); + int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + P_LINEAR : P_sRGB; + int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && + (red != green || green != blue); if (ip > 255) png_error(image->opaque->png_ptr, "color-map index out of range"); @@ -1857,13 +1875,13 @@ png_create_colormap_entry(png_image_read_control *display, /* Store the value. */ { # ifdef PNG_FORMAT_AFIRST_SUPPORTED - const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && + int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; # else # define afirst 0 # endif # ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; + int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; # else # define bgr 0 # endif @@ -1882,7 +1900,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: if (alpha < 65535) @@ -1904,7 +1922,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: if (alpha < 65535) @@ -1933,6 +1951,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_byte)alpha; + /* FALLTHROUGH */ case 3: entry[afirst + (2 ^ bgr)] = (png_byte)blue; entry[afirst + 1] = (png_byte)green; @@ -1941,6 +1960,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_byte)alpha; + /* FALLTHROUGH */ case 1: entry[afirst] = (png_byte)green; break; @@ -1967,7 +1987,7 @@ make_gray_file_colormap(png_image_read_control *display) for (i=0; i<256; ++i) png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); - return i; + return (int)i; } static int @@ -1978,7 +1998,7 @@ make_gray_colormap(png_image_read_control *display) for (i=0; i<256; ++i) png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); - return i; + return (int)i; } #define PNG_GRAY_COLORMAP_ENTRIES 256 @@ -2029,10 +2049,10 @@ make_ga_colormap(png_image_read_control *display) for (g=0; g<6; ++g) png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, - P_sRGB); + P_sRGB); } - return i; + return (int)i; } #define PNG_GA_COLORMAP_ENTRIES 256 @@ -2053,11 +2073,11 @@ make_rgb_colormap(png_image_read_control *display) for (b=0; b<6; ++b) png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, - P_sRGB); + P_sRGB); } } - return i; + return (int)i; } #define PNG_RGB_COLORMAP_ENTRIES 216 @@ -2071,11 +2091,11 @@ png_image_read_colormap(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - const png_imagep image = display->image; + png_imagep image = display->image; - const png_structrp png_ptr = image->opaque->png_ptr; - const png_uint_32 output_format = image->format; - const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + png_structrp png_ptr = image->opaque->png_ptr; + png_uint_32 output_format = image->format; + int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? P_LINEAR : P_sRGB; unsigned int cmap_entries; @@ -2105,7 +2125,7 @@ png_image_read_colormap(png_voidp argument) else if (display->background == NULL /* no way to remove it */) png_error(png_ptr, - "a background color must be supplied to remove alpha/transparency"); + "background color must be supplied to remove alpha/transparency"); /* Get a copy of the background color (this avoids repeating the checks * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the @@ -2200,7 +2220,7 @@ png_image_read_colormap(png_voidp argument) */ if (i != trans) png_create_colormap_entry(display, i, val, val, val, 255, - P_FILE/*8-bit with file gamma*/); + P_FILE/*8-bit with file gamma*/); /* Else this entry is transparent. The colors don't matter if * there is an alpha channel (back_alpha == 0), but it does no @@ -2212,7 +2232,7 @@ png_image_read_colormap(png_voidp argument) */ else png_create_colormap_entry(display, i, back_r, back_g, back_b, - back_alpha, output_encoding); + back_alpha, output_encoding); } /* We need libpng to preserve the original encoding. */ @@ -2250,7 +2270,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray[16] color-map: too few entries"); - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); if (png_ptr->num_trans > 0) { @@ -2277,7 +2297,7 @@ png_image_read_colormap(png_voidp argument) * matches. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, P_LINEAR); + back_g, 65535, P_LINEAR); } /* The background passed to libpng, however, must be the @@ -2291,8 +2311,8 @@ png_image_read_colormap(png_voidp argument) * doesn't. */ png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_NONE; break; @@ -2322,7 +2342,7 @@ png_image_read_colormap(png_voidp argument) * background color at full precision. */ png_create_colormap_entry(display, 254, back_r, back_g, back_b, - back_alpha, output_encoding); + back_alpha, output_encoding); } else @@ -2348,7 +2368,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray+alpha color-map: too few entries"); - cmap_entries = make_ga_colormap(display); + cmap_entries = (unsigned int)make_ga_colormap(display); background_index = PNG_CMAP_GA_BACKGROUND; output_processing = PNG_CMAP_GA; @@ -2382,7 +2402,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray-alpha color-map: too few entries"); - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); if (output_encoding == P_LINEAR) { @@ -2390,7 +2410,7 @@ png_image_read_colormap(png_voidp argument) /* And make sure the corresponding palette entry matches. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, P_LINEAR); + back_g, 65535, P_LINEAR); } /* The background passed to libpng, however, must be the sRGB @@ -2400,8 +2420,8 @@ png_image_read_colormap(png_voidp argument) c.gray = c.red = c.green = c.blue = (png_uint_16)gray; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_NONE; } @@ -2421,7 +2441,7 @@ png_image_read_colormap(png_voidp argument) { png_uint_32 gray = (i * 256 + 115) / 231; png_create_colormap_entry(display, i++, gray, gray, gray, - 255, P_sRGB); + 255, P_sRGB); } /* NOTE: this preserves the full precision of the application @@ -2430,13 +2450,13 @@ png_image_read_colormap(png_voidp argument) background_index = i; png_create_colormap_entry(display, i++, back_r, back_g, back_b, #ifdef __COVERITY__ - /* Coverity claims that output_encoding cannot be 2 (P_LINEAR) - * here. - */ 255U, + /* Coverity claims that output_encoding + * cannot be 2 (P_LINEAR) here. + */ 255U, #else - output_encoding == P_LINEAR ? 65535U : 255U, + output_encoding == P_LINEAR ? 65535U : 255U, #endif - output_encoding); + output_encoding); /* For non-opaque input composite on the sRGB background - this * requires inverting the encoding for each component. The input @@ -2474,9 +2494,9 @@ png_image_read_colormap(png_voidp argument) png_uint_32 gray = png_sRGB_table[g*51] * alpha; png_create_colormap_entry(display, i++, - PNG_sRGB_FROM_LINEAR(gray + back_rx), - PNG_sRGB_FROM_LINEAR(gray + back_gx), - PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); + PNG_sRGB_FROM_LINEAR(gray + back_rx), + PNG_sRGB_FROM_LINEAR(gray + back_gx), + PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); } } @@ -2502,7 +2522,7 @@ png_image_read_colormap(png_voidp argument) * png_set_tRNS_to_alpha before png_set_background_fixed. */ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, - -1); + -1); data_encoding = P_sRGB; /* The output will now be one or two 8-bit gray or gray+alpha @@ -2521,7 +2541,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "rgb[ga] color-map: too few entries"); - cmap_entries = make_ga_colormap(display); + cmap_entries = (unsigned int)make_ga_colormap(display); background_index = PNG_CMAP_GA_BACKGROUND; output_processing = PNG_CMAP_GA; } @@ -2547,12 +2567,12 @@ png_image_read_colormap(png_voidp argument) png_ptr->num_trans > 0) && png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0) { - cmap_entries = make_gray_file_colormap(display); + cmap_entries = (unsigned int)make_gray_file_colormap(display); data_encoding = P_FILE; } else - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); /* But if the input has alpha or transparency it must be removed */ @@ -2578,13 +2598,13 @@ png_image_read_colormap(png_voidp argument) gray = png_sRGB_table[gray]; /* now P_LINEAR */ gray = PNG_DIV257(png_gamma_16bit_correct(gray, - png_ptr->colorspace.gamma)); /* now P_FILE */ + png_ptr->colorspace.gamma)); /* now P_FILE */ /* And make sure the corresponding palette entry contains * exactly the required sRGB value. */ png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 0/*unused*/, output_encoding); + back_g, 0/*unused*/, output_encoding); } else if (output_encoding == P_LINEAR) @@ -2609,8 +2629,8 @@ png_image_read_colormap(png_voidp argument) */ expand_tRNS = 1; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); } output_processing = PNG_CMAP_NONE; @@ -2640,11 +2660,11 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) png_error(png_ptr, "rgb+alpha color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); /* Add a transparent entry. */ png_create_colormap_entry(display, cmap_entries, 255, 255, - 255, 0, P_sRGB); + 255, 0, P_sRGB); /* This is stored as the background index for the processing * algorithm. @@ -2665,7 +2685,7 @@ png_image_read_colormap(png_voidp argument) */ for (b=0; b<256; b = (b << 1) | 0x7f) png_create_colormap_entry(display, cmap_entries++, - r, g, b, 128, P_sRGB); + r, g, b, 128, P_sRGB); } } @@ -2689,10 +2709,10 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) png_error(png_ptr, "rgb-alpha color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); png_create_colormap_entry(display, cmap_entries, back_r, - back_g, back_b, 0/*unused*/, output_encoding); + back_g, back_b, 0/*unused*/, output_encoding); if (output_encoding == P_LINEAR) { @@ -2714,9 +2734,9 @@ png_image_read_colormap(png_voidp argument) * index. */ if (memcmp((png_const_bytep)display->colormap + - sample_size * cmap_entries, - (png_const_bytep)display->colormap + - sample_size * PNG_RGB_INDEX(r,g,b), + sample_size * cmap_entries, + (png_const_bytep)display->colormap + + sample_size * PNG_RGB_INDEX(r,g,b), sample_size) != 0) { /* The background color must be added. */ @@ -2734,13 +2754,13 @@ png_image_read_colormap(png_voidp argument) */ for (b=0; b<256; b = (b << 1) | 0x7f) png_create_colormap_entry(display, cmap_entries++, - png_colormap_compose(display, r, P_sRGB, 128, - back_r, output_encoding), - png_colormap_compose(display, g, P_sRGB, 128, - back_g, output_encoding), - png_colormap_compose(display, b, P_sRGB, 128, - back_b, output_encoding), - 0/*unused*/, output_encoding); + png_colormap_compose(display, r, P_sRGB, 128, + back_r, output_encoding), + png_colormap_compose(display, g, P_sRGB, 128, + back_g, output_encoding), + png_colormap_compose(display, b, P_sRGB, 128, + back_b, output_encoding), + 0/*unused*/, output_encoding); } } @@ -2758,8 +2778,8 @@ png_image_read_colormap(png_voidp argument) c.blue = (png_uint_16)back_b; png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); output_processing = PNG_CMAP_RGB; } @@ -2774,7 +2794,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "rgb color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); output_processing = PNG_CMAP_RGB; } } @@ -2788,7 +2808,7 @@ png_image_read_colormap(png_voidp argument) unsigned int num_trans = png_ptr->num_trans; png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; png_const_colorp colormap = png_ptr->palette; - const int do_background = trans != NULL && + int do_background = trans != NULL && (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; unsigned int i; @@ -2798,11 +2818,11 @@ png_image_read_colormap(png_voidp argument) output_processing = PNG_CMAP_NONE; data_encoding = P_FILE; /* Don't change from color-map indices */ - cmap_entries = png_ptr->num_palette; + cmap_entries = (unsigned int)png_ptr->num_palette; if (cmap_entries > 256) cmap_entries = 256; - if (cmap_entries > image->colormap_entries) + if (cmap_entries > (unsigned int)image->colormap_entries) png_error(png_ptr, "palette color-map: too few entries"); for (i=0; i < cmap_entries; ++i) @@ -2811,7 +2831,7 @@ png_image_read_colormap(png_voidp argument) { if (trans[i] == 0) png_create_colormap_entry(display, i, back_r, back_g, - back_b, 0, output_encoding); + back_b, 0, output_encoding); else { @@ -2819,22 +2839,22 @@ png_image_read_colormap(png_voidp argument) * on the sRGB color in 'back'. */ png_create_colormap_entry(display, i, - png_colormap_compose(display, colormap[i].red, P_FILE, - trans[i], back_r, output_encoding), - png_colormap_compose(display, colormap[i].green, P_FILE, - trans[i], back_g, output_encoding), - png_colormap_compose(display, colormap[i].blue, P_FILE, - trans[i], back_b, output_encoding), - output_encoding == P_LINEAR ? trans[i] * 257U : - trans[i], - output_encoding); + png_colormap_compose(display, colormap[i].red, + P_FILE, trans[i], back_r, output_encoding), + png_colormap_compose(display, colormap[i].green, + P_FILE, trans[i], back_g, output_encoding), + png_colormap_compose(display, colormap[i].blue, + P_FILE, trans[i], back_b, output_encoding), + output_encoding == P_LINEAR ? trans[i] * 257U : + trans[i], + output_encoding); } } else png_create_colormap_entry(display, i, colormap[i].red, - colormap[i].green, colormap[i].blue, - i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); + colormap[i].green, colormap[i].blue, + i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); } /* The PNG data may have indices packed in fewer than 8 bits, it @@ -2860,7 +2880,7 @@ png_image_read_colormap(png_voidp argument) case P_sRGB: /* Change to 8-bit sRGB */ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); - /* FALL THROUGH */ + /* FALLTHROUGH */ case P_FILE: if (png_ptr->bit_depth > 8) @@ -2914,7 +2934,7 @@ png_image_read_colormap(png_voidp argument) png_error(png_ptr, "bad background index (internal error)"); } - display->colormap_processing = output_processing; + display->colormap_processing = (int)output_processing; return 1/*ok*/; } @@ -2924,7 +2944,7 @@ static int png_image_read_and_map(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; int passes; @@ -3061,7 +3081,7 @@ png_image_read_and_map(png_voidp argument) if (alpha >= 196) *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], - inrow[2]); + inrow[2]); else if (alpha < 64) *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; @@ -3113,7 +3133,7 @@ static int png_image_read_colormapped(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_controlp control = image->opaque; png_structrp png_ptr = control->png_ptr; @@ -3178,8 +3198,7 @@ png_image_read_colormapped(png_voidp argument) image->colormap_entries == 244 /* 216 + 1 + 27 */) break; - /* goto bad_output; */ - /* FALL THROUGH */ + goto bad_output; default: bad_output: @@ -3223,14 +3242,14 @@ png_image_read_colormapped(png_voidp argument) else { - png_alloc_size_t row_bytes = display->row_bytes; + png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; while (--passes >= 0) { png_uint_32 y = image->height; png_bytep row = png_voidcast(png_bytep, display->first_row); - while (y-- > 0) + for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); row += row_bytes; @@ -3246,7 +3265,7 @@ static int png_image_read_composite(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; int passes; @@ -3373,7 +3392,7 @@ static int png_image_read_background(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -3433,8 +3452,7 @@ png_image_read_background(png_voidp argument) for (pass = 0; pass < passes; ++pass) { - png_bytep row = png_voidcast(png_bytep, - display->first_row); + png_bytep row = png_voidcast(png_bytep, display->first_row); unsigned int startx, stepx, stepy; png_uint_32 y; @@ -3462,7 +3480,7 @@ png_image_read_background(png_voidp argument) for (; ylocal_row); + display->local_row); png_bytep outrow = first_row + y * step_row; png_const_bytep end_row = outrow + width; @@ -3507,7 +3525,7 @@ png_image_read_background(png_voidp argument) for (; ylocal_row); + display->local_row); png_bytep outrow = first_row + y * step_row; png_const_bytep end_row = outrow + width; @@ -3554,13 +3572,14 @@ png_image_read_background(png_voidp argument) */ { png_uint_16p first_row = png_voidcast(png_uint_16p, - display->first_row); + display->first_row); /* The division by two is safe because the caller passed in a * stride which was multiplied by 2 (below) to get row_bytes. */ ptrdiff_t step_row = display->row_bytes / 2; - int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; - unsigned int outchannels = 1+preserve_alpha; + unsigned int preserve_alpha = (image->format & + PNG_FORMAT_FLAG_ALPHA) != 0; + unsigned int outchannels = 1U+preserve_alpha; int swap_alpha = 0; # ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED @@ -3604,7 +3623,7 @@ png_image_read_background(png_voidp argument) /* Read the row, which is packed: */ png_read_row(png_ptr, png_voidcast(png_bytep, - display->local_row), NULL); + display->local_row), NULL); inrow = png_voidcast(png_const_uint_16p, display->local_row); /* Now do the pre-multiplication on each pixel in this row. @@ -3653,7 +3672,7 @@ static int png_image_read_direct(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -3704,7 +3723,7 @@ png_image_read_direct(png_voidp argument) do_local_background = 1/*maybe*/; png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, - PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); + PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); } change &= ~PNG_FORMAT_FLAG_COLOR; @@ -3746,7 +3765,13 @@ png_image_read_direct(png_voidp argument) mode = PNG_ALPHA_PNG; output_gamma = PNG_DEFAULT_sRGB; } - + + if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) + { + mode = PNG_ALPHA_OPTIMIZED; + change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + /* If 'do_local_background' is set check for the presence of gamma * correction; this is part of the work-round for the libpng bug * described above. @@ -3763,7 +3788,7 @@ png_image_read_direct(png_voidp argument) * final value. */ if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, - PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) + PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) do_local_background = 0; else if (mode == PNG_ALPHA_STANDARD) @@ -3826,8 +3851,8 @@ png_image_read_direct(png_voidp argument) * pixels. */ png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); } else /* compose on row: implemented below. */ @@ -3927,7 +3952,7 @@ png_image_read_direct(png_voidp argument) */ if (linear != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; if ((*(png_const_bytep) & le) != 0) png_set_swap(png_ptr); @@ -3972,6 +3997,10 @@ png_image_read_direct(png_voidp argument) else if (do_local_compose != 0) /* internal error */ png_error(png_ptr, "png_image_read: alpha channel lost"); + if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) { + info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + if (info_ptr->bit_depth == 16) info_format |= PNG_FORMAT_FLAG_LINEAR; @@ -4057,14 +4086,14 @@ png_image_read_direct(png_voidp argument) else { - png_alloc_size_t row_bytes = display->row_bytes; + png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; while (--passes >= 0) { png_uint_32 y = image->height; png_bytep row = png_voidcast(png_bytep, display->first_row); - while (y-- > 0) + for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); row += row_bytes; @@ -4077,7 +4106,7 @@ png_image_read_direct(png_voidp argument) int PNGAPI png_image_finish_read(png_imagep image, png_const_colorp background, - void *buffer, png_int_32 row_stride, void *colormap) + void *buffer, png_int_32 row_stride, void *colormap) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -4085,29 +4114,52 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * original PNG format because it may not occur in the output PNG format * and libpng deals with the issues of reading the original. */ - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); - if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ + /* The following checks just the 'row_stride' calculation to ensure it + * fits in a signed 32-bit value. Because channels/components can be + * either 1 or 2 bytes in size the length of a row can still overflow 32 + * bits; this is just to verify that the 'row_stride' argument can be + * represented. + */ + if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (row_stride == 0) row_stride = (png_int_32)/*SAFE*/png_row_stride; if (row_stride < 0) - check = -row_stride; + check = (png_uint_32)(-row_stride); else - check = row_stride; + check = (png_uint_32)row_stride; + /* This verifies 'check', the absolute value of the actual stride + * passed in and detects overflow in the application calculation (i.e. + * if the app did actually pass in a non-zero 'row_stride'. + */ if (image->opaque != NULL && buffer != NULL && check >= png_row_stride) { /* Now check for overflow of the image buffer calculation; this * limits the whole image size to 32 bits for API compatibility with * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. + * + * The PNG_IMAGE_BUFFER_SIZE macro is: + * + * (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride)) + * + * And the component size is always 1 or 2, so make sure that the + * number of *bytes* that the application is saying are available + * does actually fit into a 32-bit number. + * + * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE + * will be changed to use png_alloc_size_t; bigger images can be + * accommodated on 64-bit systems. */ - if (image->height <= 0xFFFFFFFF/png_row_stride) + if (image->height <= + 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) { if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || (image->colormap_entries > 0 && colormap != NULL)) @@ -4127,15 +4179,16 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * all the setup has already been done. */ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0) - result = png_safe_execute(image, - png_image_read_colormap, &display) && - png_safe_execute(image, - png_image_read_colormapped, &display); + result = + png_safe_execute(image, + png_image_read_colormap, &display) && + png_safe_execute(image, + png_image_read_colormapped, &display); else result = png_safe_execute(image, - png_image_read_direct, &display); + png_image_read_direct, &display); png_image_free(image); return result; @@ -4143,27 +4196,27 @@ png_image_finish_read(png_imagep image, png_const_colorp background, else return png_image_error(image, - "png_image_finish_read[color-map]: no color-map"); + "png_image_finish_read[color-map]: no color-map"); } else return png_image_error(image, - "png_image_finish_read: image too large"); + "png_image_finish_read: image too large"); } else return png_image_error(image, - "png_image_finish_read: invalid argument"); + "png_image_finish_read: invalid argument"); } else return png_image_error(image, - "png_image_finish_read: row_stride too large"); + "png_image_finish_read: row_stride too large"); } else if (image != NULL) return png_image_error(image, - "png_image_finish_read: damaged PNG_IMAGE_VERSION"); + "png_image_finish_read: damaged PNG_IMAGE_VERSION"); return 0; } diff --git a/source/Irrlicht/libpng/pngrio.c b/source/Irrlicht/libpng/pngrio.c index 99cb5715..7d30c7a5 100644 --- a/source/Irrlicht/libpng/pngrio.c +++ b/source/Irrlicht/libpng/pngrio.c @@ -1,10 +1,10 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -29,7 +29,7 @@ * 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_read_data(png_structrp png_ptr, png_bytep data, size_t length) { png_debug1(4, "reading %d bytes", (int)length); @@ -47,14 +47,14 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_read_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + 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 + /* fread() returns 0 on error, so it is OK to store this in a 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)); @@ -85,7 +85,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) */ void PNGAPI png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) + png_rw_ptr read_data_fn) { if (png_ptr == NULL) return; diff --git a/source/Irrlicht/libpng/pngrtran.c b/source/Irrlicht/libpng/pngrtran.c index 0fc53ec6..a3cac0fc 100644 --- a/source/Irrlicht/libpng/pngrtran.c +++ b/source/Irrlicht/libpng/pngrtran.c @@ -1,10 +1,10 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.22 [May 26, 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -18,6 +18,17 @@ #include "pngpriv.h" +#ifdef PNG_ARM_NEON_IMPLEMENTATION +# if PNG_ARM_NEON_IMPLEMENTATION == 1 +# define PNG_ARM_NEON_INTRINSICS_AVAILABLE +# if defined(_MSC_VER) && defined(_M_ARM64) +# include +# else +# include +# endif +# endif +#endif + #ifdef PNG_READ_SUPPORTED /* Set the action on getting a CRC error for an ancillary or critical chunk. */ @@ -48,7 +59,8 @@ png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ png_warning(png_ptr, - "Can't discard critical data on CRC error"); + "Can't discard critical data on CRC error"); + /* FALLTHROUGH */ case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_DEFAULT: @@ -101,7 +113,7 @@ png_rtran_ok(png_structrp png_ptr, int need_IHDR) { if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) png_app_error(png_ptr, - "invalid after png_start_read_image or png_read_update_info"); + "invalid after png_start_read_image or png_read_update_info"); else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) png_app_error(png_ptr, "invalid before the PNG header has been read"); @@ -209,7 +221,7 @@ png_set_strip_alpha(png_structrp png_ptr) #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) static png_fixed_point translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, - int is_screen) + int is_screen) { /* Check for flag values. The main reason for having the old Mac value as a * flag is that it is pretty near impossible to work out what the correct @@ -273,7 +285,7 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma) #ifdef PNG_READ_ALPHA_MODE_SUPPORTED void PNGFAPI png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, - png_fixed_point output_gamma) + png_fixed_point output_gamma) { int compose = 0; png_fixed_point file_gamma; @@ -291,7 +303,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, * who use the inverse of the gamma value accidentally! Since some of these * values are reasonable this may have to be changed: * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit + * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit * gamma of 36, and its reciprocal.) */ if (output_gamma < 1000 || output_gamma > 10000000) @@ -377,7 +389,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, if ((png_ptr->transformations & PNG_COMPOSE) != 0) png_error(png_ptr, - "conflicting calls to set alpha mode and background"); + "conflicting calls to set alpha mode and background"); png_ptr->transformations |= PNG_COMPOSE; } @@ -388,7 +400,7 @@ void PNGAPI png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) { png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, - output_gamma)); + output_gamma)); } # endif #endif @@ -429,7 +441,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int i; png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); for (i = 0; i < num_palette; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -446,7 +458,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize an array to sort colors */ png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); /* Initialize the quantize_sort array */ for (i = 0; i < num_palette; i++) @@ -580,9 +592,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize palette index arrays */ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -591,7 +605,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_ptr->palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 * (sizeof (png_dsortp)))); num_new_palette = num_palette; @@ -622,7 +636,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, { t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); + (png_alloc_size_t)(sizeof (png_dsort))); if (t == NULL) break; @@ -744,12 +758,12 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); + size_t num_entries = ((size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_uint_32)(num_entries * (sizeof (png_byte)))); + (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); memset(distance, 0xff, num_entries * (sizeof (png_byte))); @@ -802,7 +816,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, #ifdef PNG_READ_GAMMA_SUPPORTED void PNGFAPI png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, - png_fixed_point file_gamma) + png_fixed_point file_gamma) { png_debug(1, "in png_set_gamma_fixed"); @@ -844,7 +858,7 @@ void PNGAPI png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) { png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), - convert_gamma_value(png_ptr, file_gamma)); + convert_gamma_value(png_ptr, file_gamma)); } # endif /* FLOATING_POINT */ #endif /* READ_GAMMA */ @@ -990,7 +1004,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, * that it just worked and get a memory overwrite. */ png_error(png_ptr, - "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ } @@ -1017,7 +1031,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, { if (red >= 0 && green >= 0) png_app_warning(png_ptr, - "ignoring out of range rgb_to_gray coefficients"); + "ignoring out of range rgb_to_gray coefficients"); /* Use the defaults, from the cHRM chunk if set, else the historical * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See @@ -1026,7 +1040,7 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, * something has already provided a default. */ if (png_ptr->rgb_to_gray_red_coeff == 0 && - png_ptr->rgb_to_gray_green_coeff == 0) + png_ptr->rgb_to_gray_green_coeff == 0) { png_ptr->rgb_to_gray_red_coeff = 6968; png_ptr->rgb_to_gray_green_coeff = 23434; @@ -1043,10 +1057,10 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, void PNGAPI png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, - double green) + double green) { png_set_rgb_to_gray_fixed(png_ptr, error_action, - png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, red, "rgb to gray red coefficient"), png_fixed(png_ptr, green, "rgb to gray green coefficient")); } #endif /* FLOATING POINT */ @@ -1168,20 +1182,20 @@ png_init_palette_transformations(png_structrp png_ptr) png_ptr->palette[png_ptr->background.index].blue; #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) - { - if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop = png_ptr->num_trans; + if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) + { + if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; - for (i=0; itrans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } + for (i = 0; i < istop; i++) + png_ptr->trans_alpha[i] = + (png_byte)(255 - png_ptr->trans_alpha[i]); + } + } #endif /* READ_INVERT_ALPHA */ } } /* background expand and (therefore) no alpha association. */ @@ -1253,7 +1267,7 @@ png_init_rgb_transformations(png_structrp png_ptr) default: case 8: - /* FALL THROUGH (Already 8 bits) */ + /* FALLTHROUGH */ /* (Already 8 bits) */ case 16: /* Already a full 16 bits */ @@ -1303,7 +1317,7 @@ png_init_read_transformations(png_structrp png_ptr) { if (png_ptr->screen_gamma != 0) /* screen set too */ gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); else /* Assume the output matches the input; a long time default behavior @@ -1314,7 +1328,7 @@ png_init_read_transformations(png_structrp png_ptr) else if (png_ptr->screen_gamma != 0) /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling + * perhaps undesirable default can (from 1.5.4) be changed by calling * png_set_alpha_mode (even if the alpha handling mode isn't required * or isn't changed from the default.) */ @@ -1584,7 +1598,7 @@ png_init_read_transformations(png_structrp png_ptr) */ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) png_warning(png_ptr, - "libpng does not support gamma+background+rgb_to_gray"); + "libpng does not support gamma+background+rgb_to_gray"); if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0) { @@ -1620,13 +1634,13 @@ png_init_read_transformations(png_structrp png_ptr) case PNG_BACKGROUND_GAMMA_FILE: g = png_reciprocal(png_ptr->colorspace.gamma); gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: g = png_reciprocal(png_ptr->background_gamma); gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; default: g = PNG_FP_1; /* back_1 */ @@ -1654,11 +1668,11 @@ png_init_read_transformations(png_structrp png_ptr) if (png_gamma_significant(g) != 0) { back_1.red = png_gamma_8bit_correct(png_ptr->background.red, - g); + g); back_1.green = png_gamma_8bit_correct( - png_ptr->background.green, g); + png_ptr->background.green, g); back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); + g); } else @@ -1729,7 +1743,7 @@ png_init_read_transformations(png_structrp png_ptr) case PNG_BACKGROUND_GAMMA_FILE: g = png_reciprocal(png_ptr->colorspace.gamma); gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); + png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: @@ -1882,7 +1896,7 @@ png_init_read_transformations(png_structrp png_ptr) png_ptr->transformations &= ~PNG_SHIFT; - /* significant bits can be in the range 1 to 7 for a meaninful result, if + /* significant bits can be in the range 1 to 7 for a meaningful result, if * the number of significant bits is 0 then no shift is done (this is an * error condition which is silently ignored.) */ @@ -2148,9 +2162,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { case 1: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + png_bytep sp = row + (size_t)((row_width - 1) >> 3); + png_bytep dp = row + (size_t)row_width - 1; + png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x01); @@ -2172,9 +2186,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 2: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + png_bytep sp = row + (size_t)((row_width - 1) >> 2); + png_bytep dp = row + (size_t)row_width - 1; + png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x03); @@ -2195,9 +2209,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 4: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + png_bytep sp = row + (size_t)((row_width - 1) >> 1); + png_bytep dp = row + (size_t)row_width - 1; + png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x0f); @@ -2460,95 +2474,94 @@ png_do_chop(png_row_infop row_info, png_bytep row) static void png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) { + png_uint_32 row_width = row_info->width; + png_debug(1, "in png_do_read_swap_alpha"); + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } -#endif } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif } } #endif @@ -2678,8 +2691,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2694,8 +2707,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2713,8 +2726,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2732,8 +2745,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2755,8 +2768,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2773,8 +2786,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2794,8 +2807,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2817,8 +2830,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2859,8 +2872,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2872,8 +2885,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2891,8 +2904,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2905,8 +2918,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 4 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2934,7 +2947,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * using the equation given in Poynton's ColorFAQ of 1998-01-04 at * (THIS LINK IS DEAD June 2008 but * versions dated 1998 through November 2002 have been archived at - * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * https://web.archive.org/web/20000816232553/www.inforamp.net/ * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) * Charles Poynton poynton at poynton.com * @@ -2977,14 +2990,13 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * values this results in an implicit assumption that the original PNG RGB * values were linear. * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * Other integer coefficients can be used via png_set_rgb_to_gray(). Because * the API takes just red and green coefficients the blue coefficient is * calculated to make the sum 32768. This will result in different rounding * to that used above. */ static int png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) - { int rgb_error = 0; @@ -2993,12 +3005,11 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 && (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) { - PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - PNG_CONST png_uint_32 bc = 32768 - rc - gc; - PNG_CONST png_uint_32 row_width = row_info->width; - PNG_CONST int have_alpha = - (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = 32768 - rc - gc; + png_uint_32 row_width = row_info->width; + int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; if (row_info->bit_depth == 8) { @@ -3206,414 +3217,229 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) png_debug(1, "in png_do_compose"); + switch (row_info->color_type) { - switch (row_info->color_type) + case PNG_COLOR_TYPE_GRAY: { - case PNG_COLOR_TYPE_GRAY: + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 7; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 7; - sp++; - } - - else - shift--; + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - break; - } - case 2: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + if (shift == 0) { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= g << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } + shift = 7; + sp++; } else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } - } - break; + shift--; } - - case 4: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= g << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - break; - } - - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - } - } - break; - } - - case 16: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - } - } - break; - } - - default: - break; + break; } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) + case 2: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + shift = 6; + for (i = 0; i < row_width; i++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); } else { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); } + + if (shift == 0) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; } } else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } + break; } - else /* if (row_info->bit_depth == 16) */ + + case 16: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - } - } - } - break; - } - - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) { sp = row; for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 a = *(sp + 1); + png_uint_16 v; - if (a == 0xff) - *sp = gamma_table[*sp]; + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - else if (a == 0) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } else { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (optimize == 0) - w = gamma_from_1[w]; - *sp = w; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } } @@ -3623,298 +3449,486 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) sp = row; for (i = 0; i < row_width; i++, sp += 2) { - png_byte a = *(sp + 1); + png_uint_16 v; - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize != 0) - w = v; - else - w = gamma_16_from_1[(v & 0xff) >> - gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == 0) + if (v == png_ptr->trans_color.gray) { *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } } } + break; } - break; + + default: + break; } - - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (optimize == 0) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 2) = w; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); - - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); - - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } - } - } - - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 v; - - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - - default: - break; + break; } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (optimize == 0) + w = gamma_from_1[w]; + *sp = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize != 0) + w = v; + else + w = gamma_16_from_1[(v & 0xff) >> + gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (optimize == 0) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 2) = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; } } #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ @@ -4138,12 +4152,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) { if (row_info->bit_depth == 8) { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; + png_bytep table = png_ptr->gamma_from_1; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; /* The alpha channel is the last component: */ row += step - 1; @@ -4157,13 +4170,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) else if (row_info->bit_depth == 16) { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; + png_uint_16pp table = png_ptr->gamma_16_from_1; + int gamma_shift = png_ptr->gamma_shift; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; /* The alpha channel is the last component: */ row += step - 2; @@ -4194,8 +4206,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * upon whether you supply trans and num_trans. */ static void -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, + int num_trans) { int shift, value; png_bytep sp, dp; @@ -4212,8 +4225,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { case 1: { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { @@ -4239,8 +4252,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 2: { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -4262,8 +4275,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 4: { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; shift = (int)((row_width & 0x01) << 2); for (i = 0; i < row_width; i++) { @@ -4296,17 +4309,30 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { if (num_trans > 0) { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 2) - 1; - for (i = 0; i < row_width; i++) + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if (png_ptr->riffled_palette != NULL) + { + /* The RGBA optimization works with png_ptr->bit_depth == 8 + * but sometimes row_info->bit_depth has been changed to 8. + * In these cases, the palette hasn't been riffled. + */ + i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row, + &sp, &dp); + } +#else + PNG_UNUSED(png_ptr) +#endif + + for (; i < row_width; i++) { if ((int)(*sp) >= num_trans) *dp-- = 0xff; - else *dp-- = trans_alpha[*sp]; - *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; *dp-- = palette[*sp].red; @@ -4321,10 +4347,17 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, else { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; + sp = row + (size_t)row_width - 1; + dp = row + (size_t)(row_width * 3) - 1; + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row, + &sp, &dp); +#else + PNG_UNUSED(png_ptr) +#endif - for (i = 0; i < row_width; i++) + for (; i < row_width; i++) { *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; @@ -4357,195 +4390,130 @@ png_do_expand(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_expand"); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + unsigned int gray = trans_color != NULL ? trans_color->gray : 0; + + if (row_info->bit_depth < 8) { - unsigned int gray = trans_color != NULL ? trans_color->gray : 0; - - if (row_info->bit_depth < 8) + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: - { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; - - dp--; - } - break; - } - - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; - } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - - else - shift = 4; - - dp--; - } - break; - } - - default: - break; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - + gray = (gray & 0x01) * 0xff; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { - if ((*sp & 0xffU) == gray) - *dp-- = 0; + if ((*sp >> shift) & 0x01) + *dp = 0xff; else - *dp-- = 0xff; + *dp = 0; - *dp-- = *sp--; - } - } - - else if (row_info->bit_depth == 16) - { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if ((*(sp - 1) & 0xffU) == gray_high && - (*(sp) & 0xffU) == gray_low) + if (shift == 7) { - *dp-- = 0; - *dp-- = 0; + shift = 0; + sp--; } else - { - *dp-- = 0xff; - *dp-- = 0xff; - } + shift++; - *dp-- = *sp--; - *dp-- = *sp--; + dp--; } + break; } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + case 2: + { + gray = (gray & 0x03) * 0x55; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (gray & 0x0f) * 0x11; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && - trans_color != NULL) + + if (trans_color != NULL) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + gray = gray & 0xff; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 1) - 1; + for (i = 0; i < row_width; i++) { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + if ((*sp & 0xffU) == gray) *dp-- = 0; else *dp-- = 0xff; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } + else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; + dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; @@ -4559,18 +4527,81 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = *sp--; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); } } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && + trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (size_t)row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } } #endif @@ -4596,7 +4627,9 @@ png_do_expand_16(png_row_infop row_info, png_bytep row) png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; + { + dp[-2] = dp[-1] = *--sp; dp -= 2; + } row_info->rowbytes *= 2; row_info->bit_depth = 16; @@ -4738,7 +4771,19 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) { if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) { - png_do_expand_palette(row_info, png_ptr->row_buf + 1, +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8)) + { + if (png_ptr->riffled_palette == NULL) + { + /* Initialize the accelerated palette expansion. */ + png_ptr->riffled_palette = + (png_bytep)png_malloc(png_ptr, 256 * 4); + png_riffle_palette_neon(png_ptr); + } + } +#endif + png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1, png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); } @@ -4750,8 +4795,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) &(png_ptr->trans_color)); else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); + png_do_expand(row_info, png_ptr->row_buf + 1, NULL); } } #endif @@ -4762,7 +4806,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); + 0 /* at_start == false, because SWAP_ALPHA happens later */); #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED @@ -4975,7 +5019,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* 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) */ diff --git a/source/Irrlicht/libpng/pngrutil.c b/source/Irrlicht/libpng/pngrutil.c index 357b1728..5e3d6ba8 100644 --- a/source/Irrlicht/libpng/pngrutil.c +++ b/source/Irrlicht/libpng/pngrutil.c @@ -1,10 +1,10 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.20 [December 3, 2014] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -86,11 +86,11 @@ png_get_int_32)(png_const_bytep buf) { png_uint_32 uval = png_get_uint_32(buf); if ((uval & 0x80000000) == 0) /* non-negative */ - return uval; + return (png_int_32)uval; uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ if ((uval & 0x80000000) == 0) /* no overflow */ - return -(png_int_32)uval; + return -(png_int_32)uval; /* The following has to be safe; this function only gets called on PNG data * and if we get here that data is invalid. 0 is the most safe value and * if not then an attacker would surely just generate a PNG with 0 instead. @@ -102,7 +102,7 @@ png_get_int_32)(png_const_bytep buf) png_uint_16 (PNGAPI png_get_uint_16)(png_const_bytep buf) { - /* ANSI-C requires an int value to accomodate at least 16 bits so this + /* ANSI-C requires an int value to accommodate at least 16 bits so this * works and allows the compiler not to worry about possible narrowing * on 32-bit systems. (Pre-ANSI systems did not make integers smaller * than 16 bits either.) @@ -120,7 +120,7 @@ png_get_uint_16)(png_const_bytep buf) void /* PRIVATE */ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked, num_to_check; + size_t num_checked, num_to_check; /* Exit if the user application does not expect a signature. */ if (png_ptr->sig_bytes >= 8) @@ -181,6 +181,9 @@ png_read_chunk_header(png_structrp png_ptr) /* Check to see if chunk name is valid. */ png_check_chunk_name(png_ptr, png_ptr->chunk_name); + /* Check for too-large chunk length */ + png_check_chunk_length(png_ptr, length); + #ifdef PNG_IO_STATE_SUPPORTED png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; #endif @@ -311,6 +314,7 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) if (buffer != NULL) { + memset(buffer, 0, new_size); /* just in case */ png_ptr->read_buffer = buffer; png_ptr->read_buffer_size = new_size; } @@ -370,11 +374,10 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) */ { int ret; /* zlib return code */ -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 + int window_bits = 0; # if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW) - int window_bits; - if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == PNG_OPTION_ON) { @@ -384,13 +387,11 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) else { - window_bits = 0; png_ptr->zstream_start = 1; } -# else -# define window_bits 0 # endif -#endif + +#endif /* ZLIB_VERNUM >= 0x1240 */ /* Set this for safety, just in case the previous owner left pointers to * memory allocations. @@ -402,25 +403,32 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) { -#if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateReset(&png_ptr->zstream); -#else +#if ZLIB_VERNUM >= 0x1240 ret = inflateReset2(&png_ptr->zstream, window_bits); +#else + ret = inflateReset(&png_ptr->zstream); #endif } else { -#if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateInit(&png_ptr->zstream); -#else +#if ZLIB_VERNUM >= 0x1240 ret = inflateInit2(&png_ptr->zstream, window_bits); +#else + ret = inflateInit(&png_ptr->zstream); #endif if (ret == Z_OK) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; } +#if ZLIB_VERNUM >= 0x1290 && \ + defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32) + if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON) + /* Turn off validation of the ADLER32 checksum in IDAT chunks */ + ret = inflateValidate(&png_ptr->zstream, 0); +#endif + if (ret == Z_OK) png_ptr->zowner = owner; @@ -435,7 +443,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) #endif } -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 /* Handle the start of the inflate stream if we called inflateInit2(strm,0); * in this case some zlib versions skip validation of the CINFO field and, in * certain circumstances, libpng may end up displaying an invalid image, in @@ -461,6 +469,7 @@ png_zlib_inflate(png_structrp png_ptr, int flush) #endif /* Zlib >= 1.2.4 */ #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED) /* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to * allow the caller to do multiple calls if required. If the 'finish' flag is * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must @@ -599,9 +608,9 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, */ static int png_decompress_chunk(png_structrp png_ptr, - png_uint_32 chunklength, png_uint_32 prefix_size, - png_alloc_size_t *newlength /* must be initialized to the maximum! */, - int terminate /*add a '\0' to the end of the uncompressed data*/) + png_uint_32 chunklength, png_uint_32 prefix_size, + png_alloc_size_t *newlength /* must be initialized to the maximum! */, + int terminate /*add a '\0' to the end of the uncompressed data*/) { /* TODO: implement different limits for different types of chunk. * @@ -638,8 +647,8 @@ png_decompress_chunk(png_structrp png_ptr, png_uint_32 lzsize = chunklength - prefix_size; ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, - /* output: */ NULL, newlength); + /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, + /* output: */ NULL, newlength); if (ret == Z_STREAM_END) { @@ -659,15 +668,17 @@ png_decompress_chunk(png_structrp png_ptr, */ png_alloc_size_t new_size = *newlength; png_alloc_size_t buffer_size = prefix_size + new_size + - (terminate != 0); + (terminate != 0); png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, - buffer_size)); + buffer_size)); if (text != NULL) { + memset(text, 0, buffer_size); + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - png_ptr->read_buffer + prefix_size, &lzsize, - text + prefix_size, newlength); + png_ptr->read_buffer + prefix_size, &lzsize, + text + prefix_size, newlength); if (ret == Z_STREAM_END) { @@ -712,7 +723,7 @@ png_decompress_chunk(png_structrp png_ptr, * the extra space may otherwise be used as a Trojan Horse. */ if (ret == Z_STREAM_END && - chunklength - prefix_size != lzsize) + chunklength - prefix_size != lzsize) png_chunk_benign_error(png_ptr, "extra compressed data"); } @@ -728,9 +739,7 @@ png_decompress_chunk(png_structrp png_ptr, { /* inflateReset failed, store the error message */ png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; + ret = PNG_UNEXPECTED_ZLIB_RETURN; } } @@ -754,6 +763,7 @@ png_decompress_chunk(png_structrp png_ptr, return Z_MEM_ERROR; } } +#endif /* READ_zTXt || READ_iTXt */ #endif /* READ_COMPRESSED_TEXT */ #ifdef PNG_READ_iCCP_SUPPORTED @@ -762,8 +772,8 @@ png_decompress_chunk(png_structrp png_ptr, */ static int png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, - png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, - int finish) + png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, + int finish) { if (png_ptr->zowner == png_ptr->chunk_name) { @@ -802,8 +812,8 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, * the available output is produced; this allows reading of truncated * streams. */ - ret = PNG_INFLATE(png_ptr, - *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); + ret = PNG_INFLATE(png_ptr, *chunk_bytes > 0 ? + Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); @@ -821,7 +831,7 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, return Z_STREAM_ERROR; } } -#endif +#endif /* READ_iCCP */ /* Read and check the IDHR chunk */ @@ -1009,7 +1019,7 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #endif { - png_crc_finish(png_ptr, (int) length - num * 3); + png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3)); } #ifndef PNG_READ_OPT_PLTE_SUPPORTED @@ -1292,7 +1302,7 @@ png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, - 1/*prefer cHRM values*/); + 1/*prefer cHRM values*/); png_colorspace_sync(png_ptr, info_ptr); } #endif @@ -1371,11 +1381,13 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * chunk is just ignored, so does not invalidate the color space. An * alternative is to set the 'invalid' flags at the start of this routine * and only clear them in they were not set before and all the tests pass. - * The minimum 'deflate' stream is assumed to be just the 2 byte header and - * 4 byte checksum. The keyword must be at least one character and there is - * a terminator (0) byte and the compression method. */ - if (length < 9) + + /* The keyword must be at least one character and there is a + * terminator (0) byte and the compression method byte, and the + * 'zlib' datastream is at least 11 bytes. + */ + if (length < 14) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "too short"); @@ -1407,6 +1419,16 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_crc_read(png_ptr, (png_bytep)keyword, read_length); length -= read_length; + /* The minimum 'zlib' stream is assumed to be just the 2 byte header, + * 5 bytes minimum 'deflate' stream, and the 4 byte checksum. + */ + if (length < 11) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + keyword_length = 0; while (keyword_length < 80 && keyword_length < read_length && keyword[keyword_length] != 0) @@ -1425,53 +1447,52 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) { - Byte profile_header[132]; + Byte profile_header[132]={0}; Byte local_buffer[PNG_INFLATE_BUF_SIZE]; png_alloc_size_t size = (sizeof profile_header); png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); png_ptr->zstream.avail_in = read_length; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, profile_header, &size, - 0/*finish: don't, because the output is too small*/); + (sizeof local_buffer), &length, profile_header, &size, + 0/*finish: don't, because the output is too small*/); if (size == 0) { /* We have the ICC profile header; do the basic header checks. */ - const png_uint_32 profile_length = - png_get_uint_32(profile_header); + png_uint_32 profile_length = png_get_uint_32(profile_header); if (png_icc_check_length(png_ptr, &png_ptr->colorspace, - keyword, profile_length) != 0) + keyword, profile_length) != 0) { /* The length is apparently ok, so we can check the 132 * byte header. */ if (png_icc_check_header(png_ptr, &png_ptr->colorspace, - keyword, profile_length, profile_header, - png_ptr->color_type) != 0) + keyword, profile_length, profile_header, + png_ptr->color_type) != 0) { /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole * profile. The header check has already validated - * that none of these stuff will overflow. + * that none of this stuff will overflow. */ - const png_uint_32 tag_count = png_get_uint_32( - profile_header+128); + png_uint_32 tag_count = + png_get_uint_32(profile_header + 128); png_bytep profile = png_read_buffer(png_ptr, - profile_length, 2/*silent*/); + profile_length, 2/*silent*/); if (profile != NULL) { memcpy(profile, profile_header, - (sizeof profile_header)); + (sizeof profile_header)); size = 12 * tag_count; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header), &size, 0); + (sizeof local_buffer), &length, + profile + (sizeof profile_header), &size, 0); /* Still expect a buffer error because we expect * there to be some tag data! @@ -1479,22 +1500,22 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (size == 0) { if (png_icc_check_tag_table(png_ptr, - &png_ptr->colorspace, keyword, profile_length, - profile) != 0) + &png_ptr->colorspace, keyword, profile_length, + profile) != 0) { /* The profile has been validated for basic * security issues, so read the whole thing in. */ size = profile_length - (sizeof profile_header) - - 12 * tag_count; + - 12 * tag_count; (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header) + - 12 * tag_count, &size, 1/*finish*/); + (sizeof local_buffer), &length, + profile + (sizeof profile_header) + + 12 * tag_count, &size, 1/*finish*/); if (length > 0 && !(png_ptr->flags & - PNG_FLAG_BENIGN_ERRORS_WARN)) + PNG_FLAG_BENIGN_ERRORS_WARN)) errmsg = "extra compressed data"; /* But otherwise allow extra data: */ @@ -1506,34 +1527,34 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * keep going. */ png_chunk_warning(png_ptr, - "extra compressed data"); + "extra compressed data"); } png_crc_finish(png_ptr, length); finished = 1; -# ifdef PNG_sRGB_SUPPORTED +# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 /* Check for a match against sRGB */ png_icc_set_sRGB(png_ptr, - &png_ptr->colorspace, profile, - png_ptr->zstream.adler); -# endif + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); +# endif /* Steal the profile for info_ptr. */ if (info_ptr != NULL) { png_free_data(png_ptr, info_ptr, - PNG_FREE_ICCP, 0); + PNG_FREE_ICCP, 0); info_ptr->iccp_name = png_voidcast(char*, - png_malloc_base(png_ptr, - keyword_length+1)); + png_malloc_base(png_ptr, + keyword_length+1)); if (info_ptr->iccp_name != NULL) { memcpy(info_ptr->iccp_name, keyword, - keyword_length+1); + keyword_length+1); info_ptr->iccp_proflen = - profile_length; + profile_length; info_ptr->iccp_profile = profile; png_ptr->read_buffer = NULL; /*steal*/ info_ptr->free_me |= PNG_FREE_ICCP; @@ -1562,19 +1583,11 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } } - - else if (size > 0) - errmsg = "truncated"; - -#ifndef __COVERITY__ - else + if (errmsg == NULL) errmsg = png_ptr->zstream.msg; -#endif } - /* else png_icc_check_tag_table output an error */ } - else /* profile truncated */ errmsg = png_ptr->zstream.msg; } @@ -1634,7 +1647,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) int entry_size, i; png_uint_32 skip = 0; png_uint_32 dl; - png_size_t max_dl; + size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -1715,13 +1728,13 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) data_length = length - (png_uint_32)(entry_start - buffer); /* Integrity-check the data length */ - if ((data_length % entry_size) != 0) + if ((data_length % (unsigned int)entry_size) != 0) { png_warning(png_ptr, "sPLT chunk has bad length"); return; } - dl = (png_int_32)(data_length / entry_size); + dl = (png_uint_32)(data_length / (unsigned int)entry_size); max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry)); if (dl > max_dl) @@ -1730,10 +1743,10 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } - new_palette.nentries = (png_int_32)(data_length / entry_size); + new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size); - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry))); + new_palette.entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_alloc_size_t) new_palette.nentries * (sizeof (png_sPLT_entry))); if (new_palette.entries == NULL) { @@ -1983,6 +1996,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */ { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth)) + { + png_chunk_benign_error(png_ptr, "invalid gray level"); + return; + } + } + background.index = 0; background.red = background.green = @@ -1992,6 +2014,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0) + { + png_chunk_benign_error(png_ptr, "invalid color"); + return; + } + } + background.index = 0; background.red = png_get_uint_16(buf); background.green = png_get_uint_16(buf + 2); @@ -2003,6 +2034,69 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif +#ifdef PNG_READ_eXIf_SUPPORTED +void /* PRIVATE */ +png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int i; + + png_debug(1, "in png_handle_eXIf"); + + if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); + + if (length < 2) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + + else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + info_ptr->eXIf_buf = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->eXIf_buf == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + for (i = 0; i < length; i++) + { + png_byte buf[1]; + png_crc_read(png_ptr, buf, 1); + info_ptr->eXIf_buf[i] = buf[0]; + if (i == 1 && buf[0] != 'M' && buf[0] != 'I' + && info_ptr->eXIf_buf[0] != buf[0]) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "incorrect byte-order specifier"); + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + return; + } + } + + if (png_crc_finish(png_ptr, 0) != 0) + return; + + png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf); + + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; +} +#endif + #ifdef PNG_READ_hIST_SUPPORTED void /* PRIVATE */ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) @@ -2270,7 +2364,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, - (png_charp)units, params); + (png_charp)units, params); png_free(png_ptr, params); } @@ -2282,7 +2376,7 @@ void /* PRIVATE */ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_bytep buffer; - png_size_t i; + size_t i; int state; png_debug(1, "in png_handle_sCAL"); @@ -2313,7 +2407,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", - length + 1); + length + 1); buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); @@ -2352,7 +2446,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { - png_size_t heighti = i; + size_t heighti = i; state = 0; if (png_check_fp_number((png_const_charp)buffer, length, @@ -2365,7 +2459,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else /* This is the (only) success case. */ png_set_sCAL_s(png_ptr, info_ptr, buffer[0], - (png_charp)buffer+1, (png_charp)buffer+heighti); + (png_charp)buffer+1, (png_charp)buffer+heighti); } } #endif @@ -2465,8 +2559,8 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (buffer == NULL) { - png_chunk_benign_error(png_ptr, "out of memory"); - return; + png_chunk_benign_error(png_ptr, "out of memory"); + return; } png_crc_read(png_ptr, buffer, length); @@ -2531,6 +2625,9 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) png_ptr->mode |= PNG_AFTER_IDAT; + /* Note, "length" is sufficient here; we won't be adding + * a null terminator later. + */ buffer = png_read_buffer(png_ptr, length, 2/*silent*/); if (buffer == NULL) @@ -2573,27 +2670,32 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * and text chunks. */ if (png_decompress_chunk(png_ptr, length, keyword_length+2, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) { png_text text; - /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except - * for the extra compression type byte and the fact that it isn't - * necessarily '\0' terminated. - */ - buffer = png_ptr->read_buffer; - buffer[uncompressed_length+(keyword_length+2)] = 0; + if (png_ptr->read_buffer == NULL) + errmsg="Read failure in png_handle_zTXt"; + else + { + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk + * except for the extra compression type byte and the fact that + * it isn't necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; - text.compression = PNG_TEXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.text = (png_charp)(buffer + keyword_length+2); - text.text_length = uncompressed_length; - text.itxt_length = 0; - text.lang = NULL; - text.lang_key = NULL; + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (png_charp)buffer; + text.text = (png_charp)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; - if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) - errmsg = "insufficient memory"; + if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) + errmsg = "insufficient memory"; + } } else @@ -2713,7 +2815,7 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * iCCP and text chunks. */ if (png_decompress_chunk(png_ptr, length, prefix_length, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) buffer = png_ptr->read_buffer; else @@ -2782,7 +2884,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) { PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/; /* 'mode' is a flag array, only the bottom four bits matter here */ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; @@ -2793,7 +2895,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) { /* Do a 'warn' here - it is handled below. */ png_ptr->unknown_chunk.data = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, length)); + png_malloc_warn(png_ptr, length)); } } @@ -2818,7 +2920,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) /* Handle an unknown, or known but disabled, chunk */ void /* PRIVATE */ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, - png_uint_32 length, int keep) + png_uint_32 length, int keep) { int handled = 0; /* the chunk was handled */ @@ -2856,7 +2958,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, { /* Callback to user unknown chunk handler */ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, - &png_ptr->unknown_chunk); + &png_ptr->unknown_chunk); /* ret is: * negative: An error occurred; png_chunk_error will be called. @@ -2890,9 +2992,9 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, { png_chunk_warning(png_ptr, "Saving unknown chunk:"); png_app_warning(png_ptr, - "forcing save of an unhandled chunk;" - " please call png_set_keep_unknown_chunks"); - /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ + "forcing save of an unhandled chunk;" + " please call png_set_keep_unknown_chunks"); + /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ } # endif keep = PNG_HANDLE_CHUNK_IF_SAFE; @@ -2969,7 +3071,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, case 2: png_ptr->user_chunk_cache_max = 1; png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical * chunk being skipped, now there will be a hard error below. @@ -2978,14 +3080,14 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, default: /* not at limit */ --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 0: /* no limit */ # endif /* USER_LIMITS */ /* Here when the limit isn't reached or when limits are compiled * out; store the chunk. */ png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); + &png_ptr->unknown_chunk, 1); handled = 1; # ifdef PNG_USER_LIMITS_SUPPORTED break; @@ -3029,20 +3131,61 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, */ void /* PRIVATE */ -png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) +png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name) { int i; + png_uint_32 cn=chunk_name; png_debug(1, "in png_check_chunk_name"); for (i=1; i<=4; ++i) { - int c = chunk_name & 0xff; + int c = cn & 0xff; if (c < 65 || c > 122 || (c > 90 && c < 97)) png_chunk_error(png_ptr, "invalid chunk type"); - chunk_name >>= 8; + cn >>= 8; + } +} + +void /* PRIVATE */ +png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length) +{ + png_alloc_size_t limit = PNG_UINT_31_MAX; + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + if (png_ptr->chunk_name == png_IDAT) + { + png_alloc_size_t idat_limit = PNG_UINT_31_MAX; + size_t row_factor = + (size_t)png_ptr->width + * (size_t)png_ptr->channels + * (png_ptr->bit_depth > 8? 2: 1) + + 1 + + (png_ptr->interlaced? 6: 0); + if (png_ptr->height > PNG_UINT_32_MAX/row_factor) + idat_limit = PNG_UINT_31_MAX; + else + idat_limit = png_ptr->height * row_factor; + row_factor = row_factor > 32566? 32566 : row_factor; + idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */ + idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX; + limit = limit < idat_limit? idat_limit : limit; + } + + if (length > limit) + { + png_debug2(0," length = %lu, limit = %lu", + (unsigned long)length,(unsigned long)limit); + png_chunk_error(png_ptr, "chunk data is too large"); } } @@ -3097,7 +3240,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) # ifdef PNG_READ_PACKSWAP_SUPPORTED if ((png_ptr->transformations & PNG_PACKSWAP) != 0) /* little-endian byte */ - end_mask = 0xff << end_mask; + end_mask = (unsigned int)(0xff << end_mask); else /* big-endian byte */ # endif @@ -3219,7 +3362,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and * then pass: */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = { /* Little-endian byte masks for PACKSWAP */ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, @@ -3230,7 +3373,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* display_mask has only three entries for the odd passes, so index by * pass>>1. */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = + static const png_uint_32 display_mask[2][3][3] = { /* Little-endian byte masks for PACKSWAP */ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, @@ -3371,7 +3514,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ do { - dp[0] = sp[0], dp[1] = sp[1]; + dp[0] = sp[0]; dp[1] = sp[1]; if (row_width <= bytes_to_jump) return; @@ -3392,7 +3535,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ for (;;) { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2]; if (row_width <= bytes_to_jump) return; @@ -3418,8 +3561,8 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* Everything is aligned for png_uint_16 copies, but try for * png_uint_32 first. */ - if (png_isaligned(dp, png_uint_32) != 0 && - png_isaligned(sp, png_uint_32) != 0 && + if (png_isaligned(dp, png_uint_32) && + png_isaligned(sp, png_uint_32) && bytes_to_copy % (sizeof (png_uint_32)) == 0 && bytes_to_jump % (sizeof (png_uint_32)) == 0) { @@ -3539,11 +3682,11 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) #ifdef PNG_READ_INTERLACING_SUPPORTED void /* PRIVATE */ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations /* Because these may affect the byte layout */) + png_uint_32 transformations /* Because these may affect the byte layout */) { /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Offset to next interlace block */ - static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; png_debug(1, "in png_do_read_interlace"); if (row != NULL && row_info != NULL) @@ -3556,11 +3699,12 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { case 1: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; + png_bytep sp = row + (size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (size_t)((final_width - 1) >> 3); + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; + int jstop = (int)png_pass_inc[pass]; png_byte v; png_uint_32 i; int j; @@ -3568,8 +3712,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); + sshift = ((row_info->width + 7) & 0x07); + dshift = ((final_width + 7) & 0x07); s_start = 7; s_end = 0; s_inc = -1; @@ -3578,8 +3722,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); + sshift = 7 - ((row_info->width + 7) & 0x07); + dshift = 7 - ((final_width + 7) & 0x07); s_start = 0; s_end = 7; s_inc = 1; @@ -3591,7 +3735,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0x7f7f >> (7 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3601,7 +3745,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3611,7 +3755,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } @@ -3620,16 +3764,17 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; + int jstop = (int)png_pass_inc[pass]; png_uint_32 i; #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); + sshift = (((row_info->width + 3) & 0x03) << 1); + dshift = (((final_width + 3) & 0x03) << 1); s_start = 6; s_end = 0; s_inc = -2; @@ -3638,8 +3783,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + sshift = ((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = ((3 - ((final_width + 3) & 0x03)) << 1); s_start = 0; s_end = 6; s_inc = 2; @@ -3654,7 +3799,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0x3f3f >> (6 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3664,7 +3809,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3674,25 +3819,26 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } case 4: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; + png_bytep sp = row + (size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (size_t)((final_width - 1) >> 1); + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; png_uint_32 i; - int jstop = png_pass_inc[pass]; + int jstop = (int)png_pass_inc[pass]; #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); + sshift = (((row_info->width + 1) & 0x01) << 2); + dshift = (((final_width + 1) & 0x01) << 2); s_start = 4; s_end = 0; s_inc = -4; @@ -3701,8 +3847,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + sshift = ((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = ((1 - ((final_width + 1) & 0x01)) << 2); s_start = 0; s_end = 4; s_inc = 4; @@ -3716,7 +3862,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0xf0f >> (4 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3726,7 +3872,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3736,21 +3882,21 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } default: { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) + png_bytep sp = row + (size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + png_bytep dp = row + (size_t)(final_width - 1) * pixel_bytes; - int jstop = png_pass_inc[pass]; + int jstop = (int)png_pass_inc[pass]; png_uint_32 i; for (i = 0; i < row_info->width; i++) @@ -3783,10 +3929,10 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, static void png_read_filter_row_sub(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; @@ -3801,10 +3947,10 @@ png_read_filter_row_sub(png_row_infop row_info, png_bytep row, static void png_read_filter_row_up(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; png_bytep rp = row; png_const_bytep pp = prev_row; @@ -3817,13 +3963,13 @@ png_read_filter_row_up(png_row_infop row_info, png_bytep row, static void png_read_filter_row_avg(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { - png_size_t i; + size_t i; png_bytep rp = row; png_const_bytep pp = prev_row; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -3844,7 +3990,7 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row, static void png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { png_bytep rp_end = row + row_info->rowbytes; int a, c; @@ -3878,7 +4024,10 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, /* Find the best predictor, the least of pa, pb, pc favoring the earlier * ones in the case of a tie. */ - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; /* Calculate the current pixel in a, and move the previous row pixel to c @@ -3892,9 +4041,9 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, static void png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) + png_const_bytep prev_row) { - int bpp = (row_info->pixel_depth + 7) >> 3; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp_end = row + bpp; /* Process the first pixel in the row completely (this is the same as 'up' @@ -3907,7 +4056,7 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, } /* Remainder */ - rp_end += row_info->rowbytes - bpp; + rp_end = rp_end + (row_info->rowbytes - bpp); while (row < rp_end) { @@ -3930,7 +4079,10 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; a += *row; @@ -3977,7 +4129,7 @@ png_init_filter_functions(png_structrp pp) void /* PRIVATE */ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) + png_const_bytep prev_row, int filter) { /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic @@ -3995,7 +4147,7 @@ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, #ifdef PNG_SEQUENTIAL_READ_SUPPORTED void /* PRIVATE */ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, - png_alloc_size_t avail_out) + png_alloc_size_t avail_out) { /* Loop reading IDATs and decompressing the result into output[avail_out] */ png_ptr->zstream.next_out = output; @@ -4176,16 +4328,16 @@ png_read_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; png_debug(1, "in png_read_finish_row"); png_ptr->row_number++; @@ -4241,19 +4393,19 @@ png_read_start_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; - int max_pixel_depth; - png_size_t row_bytes; + unsigned int max_pixel_depth; + size_t row_bytes; png_debug(1, "in png_read_start_row"); @@ -4281,7 +4433,7 @@ png_read_start_row(png_structrp png_ptr) png_ptr->iwidth = png_ptr->width; } - max_pixel_depth = png_ptr->pixel_depth; + max_pixel_depth = (unsigned int)png_ptr->pixel_depth; /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of * calculations to calculate the final pixel depth, then @@ -4416,7 +4568,7 @@ png_read_start_row(png_structrp png_ptr) defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) { - int user_pixel_depth = png_ptr->user_transform_depth * + unsigned int user_pixel_depth = png_ptr->user_transform_depth * png_ptr->user_transform_channels; if (user_pixel_depth > max_pixel_depth) @@ -4438,7 +4590,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * for safety's sake */ row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); + 1 + ((max_pixel_depth + 7) >> 3U); #ifdef PNG_MAX_MALLOC_64K if (row_bytes > (png_uint_32)65536L) @@ -4447,42 +4599,42 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if (row_bytes + 48 > png_ptr->old_big_row_buf_size) { - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); - if (png_ptr->interlaced != 0) - png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, - row_bytes + 48); + if (png_ptr->interlaced != 0) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); - else - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); #ifdef PNG_ALIGNED_MEMORY_SUPPORTED - /* Use 16-byte aligned memory for row_buf with at least 16 bytes - * of padding before and after row_buf; treat prev_row similarly. - * NOTE: the alignment is to the start of the pixels, one beyond the start - * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this - * was incorrect; the filter byte was aligned, which had the exact - * opposite effect of that intended. - */ - { - png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->row_buf = temp - extra - 1/*filter byte*/; + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf; treat prev_row similarly. + * NOTE: the alignment is to the start of the pixels, one beyond the start + * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this + * was incorrect; the filter byte was aligned, which had the exact + * opposite effect of that intended. + */ + { + png_bytep temp = png_ptr->big_row_buf + 32; + int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->row_buf = temp - extra - 1/*filter byte*/; - temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->prev_row = temp - extra - 1/*filter byte*/; - } + temp = png_ptr->big_prev_row + 32; + extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->prev_row = temp - extra - 1/*filter byte*/; + } #else - /* Use 31 bytes of padding before and 17 bytes after row_buf. */ - png_ptr->row_buf = png_ptr->big_row_buf + 31; - png_ptr->prev_row = png_ptr->big_prev_row + 31; + /* Use 31 bytes of padding before and 17 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 31; + png_ptr->prev_row = png_ptr->big_prev_row + 31; #endif - png_ptr->old_big_row_buf_size = row_bytes + 48; + png_ptr->old_big_row_buf_size = row_bytes + 48; } #ifdef PNG_MAX_MALLOC_64K @@ -4507,7 +4659,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * does not, so free the read buffer now regardless; the sequential reader * reallocates it on demand. */ - if (png_ptr->read_buffer != 0) + if (png_ptr->read_buffer != NULL) { png_bytep buffer = png_ptr->read_buffer; diff --git a/source/Irrlicht/libpng/pngset.c b/source/Irrlicht/libpng/pngset.c index b050e95a..b8889be7 100644 --- a/source/Irrlicht/libpng/pngset.c +++ b/source/Irrlicht/libpng/pngset.c @@ -1,10 +1,10 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.23 [June 9, 2016] - * Copyright (c) 1998-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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -104,14 +104,14 @@ png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, double green_x, double green_y, double blue_x, double blue_y) { png_set_cHRM_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, white_x, "cHRM White X"), - png_fixed(png_ptr, white_y, "cHRM White Y"), - png_fixed(png_ptr, red_x, "cHRM Red X"), - png_fixed(png_ptr, red_y, "cHRM Red Y"), - png_fixed(png_ptr, green_x, "cHRM Green X"), - png_fixed(png_ptr, green_y, "cHRM Green Y"), - png_fixed(png_ptr, blue_x, "cHRM Blue X"), - png_fixed(png_ptr, blue_y, "cHRM Blue Y")); + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); } void PNGAPI @@ -120,20 +120,67 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, double blue_X, double blue_Y, double blue_Z) { png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, red_X, "cHRM Red X"), - png_fixed(png_ptr, red_Y, "cHRM Red Y"), - png_fixed(png_ptr, red_Z, "cHRM Red Z"), - png_fixed(png_ptr, green_X, "cHRM Green X"), - png_fixed(png_ptr, green_Y, "cHRM Green Y"), - png_fixed(png_ptr, green_Z, "cHRM Green Z"), - png_fixed(png_ptr, blue_X, "cHRM Blue X"), - png_fixed(png_ptr, blue_Y, "cHRM Blue Y"), - png_fixed(png_ptr, blue_Z, "cHRM Blue Z")); + png_fixed(png_ptr, red_X, "cHRM Red X"), + png_fixed(png_ptr, red_Y, "cHRM Red Y"), + png_fixed(png_ptr, red_Z, "cHRM Red Z"), + png_fixed(png_ptr, green_X, "cHRM Green X"), + png_fixed(png_ptr, green_Y, "cHRM Green Y"), + png_fixed(png_ptr, green_Z, "cHRM Green Z"), + png_fixed(png_ptr, blue_X, "cHRM Blue X"), + png_fixed(png_ptr, blue_Y, "cHRM Blue Y"), + png_fixed(png_ptr, blue_Z, "cHRM Blue Z")); } # endif /* FLOATING_POINT */ #endif /* cHRM */ +#ifdef PNG_eXIf_SUPPORTED +void PNGAPI +png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep eXIf_buf) +{ + png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(eXIf_buf) +} + +void PNGAPI +png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_32 num_exif, png_bytep eXIf_buf) +{ + int i; + + png_debug1(1, "in %s storage function", "eXIf"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + + info_ptr->num_exif = num_exif; + + info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, + info_ptr->num_exif)); + + if (info_ptr->exif == NULL) + { + png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + for (i = 0; i < (int) info_ptr->num_exif; i++) + info_ptr->exif[i] = eXIf_buf[i]; + + info_ptr->valid |= PNG_INFO_eXIf; +} +#endif /* eXIf */ + #ifdef PNG_gAMA_SUPPORTED void PNGFAPI png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, @@ -266,7 +313,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params) { - png_size_t length; + size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); @@ -283,17 +330,29 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, /* Check that the type matches the specification. */ if (type < 0 || type > 3) - png_error(png_ptr, "Invalid pCAL equation type"); + { + png_chunk_report(png_ptr, "Invalid pCAL equation type", + PNG_CHUNK_WRITE_ERROR); + return; + } if (nparams < 0 || nparams > 255) - png_error(png_ptr, "Invalid pCAL parameter count"); + { + png_chunk_report(png_ptr, "Invalid pCAL parameter count", + PNG_CHUNK_WRITE_ERROR); + return; + } /* Validate params[nparams] */ for (i=0; ipcal_purpose = png_voidcast(png_charp, @@ -301,8 +360,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_purpose == NULL) { - png_warning(png_ptr, "Insufficient memory for pCAL purpose"); - + png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose", + PNG_CHUNK_WRITE_ERROR); return; } @@ -316,10 +375,10 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, length = strlen(units) + 1; png_debug1(3, "allocating units for info (%lu bytes)", - (unsigned long)length); + (unsigned long)length); info_ptr->pcal_units = png_voidcast(png_charp, - png_malloc_warn(png_ptr, length)); + png_malloc_warn(png_ptr, length)); if (info_ptr->pcal_units == NULL) { @@ -331,7 +390,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)((nparams + 1) * (sizeof (png_charp))))); + (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); if (info_ptr->pcal_params == NULL) { @@ -340,7 +399,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, return; } - memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); + memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) * + (sizeof (png_charp))); for (i = 0; i < nparams; i++) { @@ -370,7 +430,7 @@ void PNGAPI png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, int unit, png_const_charp swidth, png_const_charp sheight) { - png_size_t lengthw = 0, lengthh = 0; + size_t lengthw = 0, lengthh = 0; png_debug1(1, "in %s storage function", "sCAL"); @@ -398,7 +458,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); info_ptr->scal_s_width = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthw)); + png_malloc_warn(png_ptr, lengthw)); if (info_ptr->scal_s_width == NULL) { @@ -414,7 +474,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); info_ptr->scal_s_height = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthh)); + png_malloc_warn(png_ptr, lengthh)); if (info_ptr->scal_s_height == NULL) { @@ -453,9 +513,9 @@ png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, char sheight[PNG_sCAL_MAX_DIGITS+1]; png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, - PNG_sCAL_PRECISION); + PNG_sCAL_PRECISION); png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, - PNG_sCAL_PRECISION); + PNG_sCAL_PRECISION); png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); } @@ -563,7 +623,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); if (num_palette > 0) - memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); + memcpy(png_ptr->palette, palette, (unsigned int)num_palette * + (sizeof (png_color))); info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; @@ -630,7 +691,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, { png_charp new_iccp_name; png_bytep new_iccp_profile; - png_size_t length; + size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -648,7 +709,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, */ { int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, - proflen, profile, info_ptr->color_type); + proflen, profile, info_ptr->color_type); png_colorspace_sync_info(png_ptr, info_ptr); @@ -673,7 +734,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(new_iccp_name, name, length); new_iccp_profile = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, proflen)); + png_malloc_warn(png_ptr, proflen)); if (new_iccp_profile == NULL) { @@ -748,14 +809,14 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, * the overflow checks. */ new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, - info_ptr->text, old_num_text, max_text-old_num_text, - sizeof *new_text)); + info_ptr->text, old_num_text, max_text-old_num_text, + sizeof *new_text)); } if (new_text == NULL) { png_chunk_report(png_ptr, "too many text chunks", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return 1; } @@ -783,7 +844,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) { png_chunk_report(png_ptr, "text compression mode is out of range", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); continue; } @@ -815,7 +876,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, # else /* iTXt */ { png_chunk_report(png_ptr, "iTXt chunk not supported", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); continue; } # endif @@ -844,7 +905,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, if (textp->key == NULL) { png_chunk_report(png_ptr, "text chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return 1; } @@ -956,8 +1017,8 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, { /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ info_ptr->trans_alpha = png_voidcast(png_bytep, - png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); + memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -976,7 +1037,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, trans_color->green > sample_max || trans_color->blue > sample_max))) png_warning(png_ptr, - "tRNS chunk has out-of-range samples for bit_depth"); + "tRNS chunk has out-of-range samples for bit_depth"); } #endif @@ -1018,8 +1079,8 @@ png_set_sPLT(png_const_structrp png_ptr, * overflows. Notice that the parameters are (int) and (size_t) */ np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, - info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, - sizeof *np)); + info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, + sizeof *np)); if (np == NULL) { @@ -1037,7 +1098,7 @@ png_set_sPLT(png_const_structrp png_ptr, do { - png_size_t length; + size_t length; /* Skip invalid input entries */ if (entries->name == NULL || entries->entries == NULL) @@ -1080,7 +1141,7 @@ png_set_sPLT(png_const_structrp png_ptr, * checked it when doing the allocation. */ memcpy(np->entries, entries->entries, - entries->nentries * sizeof (png_sPLT_entry)); + (unsigned int)entries->nentries * sizeof (png_sPLT_entry)); /* Note that 'continue' skips the advance of the out pointer and out * count, so an invalid entry is not added. @@ -1088,8 +1149,9 @@ png_set_sPLT(png_const_structrp png_ptr, info_ptr->valid |= PNG_INFO_sPLT; ++(info_ptr->splt_palettes_num); ++np; + ++entries; } - while (++entries, --nentries); + while (--nentries); if (nentries > 0) png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); @@ -1110,10 +1172,10 @@ check_location(png_const_structrp png_ptr, int location) { /* Write struct, so unknown chunks come from the app */ png_app_warning(png_ptr, - "png_set_unknown_chunks now expects a valid location"); + "png_set_unknown_chunks now expects a valid location"); /* Use the old behavior */ location = (png_byte)(png_ptr->mode & - (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); + (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); } /* This need not be an internal error - if the app calls @@ -1136,7 +1198,7 @@ check_location(png_const_structrp png_ptr, int location) void PNGAPI png_set_unknown_chunks(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) + png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) { png_unknown_chunkp np; @@ -1175,13 +1237,13 @@ png_set_unknown_chunks(png_const_structrp png_ptr, * appropriate to read or write. */ np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, - info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, - sizeof *np)); + info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, + sizeof *np)); if (np == NULL) { png_chunk_report(png_ptr, "too many unknown chunks", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); return; } @@ -1210,12 +1272,12 @@ png_set_unknown_chunks(png_const_structrp png_ptr, else { np->data = png_voidcast(png_bytep, - png_malloc_base(png_ptr, unknowns->size)); + png_malloc_base(png_ptr, unknowns->size)); if (np->data == NULL) { png_chunk_report(png_ptr, "unknown chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); + PNG_CHUNK_WRITE_ERROR); /* But just skip storing the unknown chunk */ continue; } @@ -1249,7 +1311,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, { png_app_error(png_ptr, "invalid unknown chunk location"); /* Fake out the pre 1.6.0 behavior: */ - if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */ + if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */ location = PNG_AFTER_IDAT; else @@ -1337,9 +1399,10 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, /* Ignore all unknown chunks and all chunks recognized by * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND */ - static PNG_CONST png_byte chunks_to_ignore[] = { + static const png_byte chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 101, 88, 73, 102, '\0', /* eXIf */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ 105, 67, 67, 80, '\0', /* iCCP */ @@ -1373,7 +1436,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, return; } - num_chunks = num_chunks_in; + num_chunks = (unsigned int)num_chunks_in; } old_num_chunks = png_ptr->num_chunk_list; @@ -1422,7 +1485,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, for (i=0; i PNG_UINT_31_MAX) - png_error(png_ptr, "invalid compression buffer size"); + if (size == 0 || size > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid compression buffer size"); # ifdef PNG_SEQUENTIAL_READ_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) - { - png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ - return; - } + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) + { + png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ + return; + } # endif # ifdef PNG_WRITE_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) + if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) + { + if (png_ptr->zowner != 0) { - if (png_ptr->zowner != 0) - { - png_warning(png_ptr, - "Compression buffer size cannot be changed because it is in use"); + png_warning(png_ptr, + "Compression buffer size cannot be changed because it is in use"); - return; - } + return; + } #ifndef __COVERITY__ - /* Some compilers complain that this is always false. However, it - * can be true when integer overflow happens. - */ - if (size > ZLIB_IO_MAX) - { - png_warning(png_ptr, - "Compression buffer size limited to system maximum"); - size = ZLIB_IO_MAX; /* must fit */ - } + /* Some compilers complain that this is always false. However, it + * can be true when integer overflow happens. + */ + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, + "Compression buffer size limited to system maximum"); + size = ZLIB_IO_MAX; /* must fit */ + } #endif - if (size < 6) - { - /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH - * if this is permitted. - */ - png_warning(png_ptr, - "Compression buffer size cannot be reduced below 6"); + if (size < 6) + { + /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH + * if this is permitted. + */ + png_warning(png_ptr, + "Compression buffer size cannot be reduced below 6"); - return; - } - - if (png_ptr->zbuffer_size != size) - { - png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); - png_ptr->zbuffer_size = (uInt)size; - } + return; } + + if (png_ptr->zbuffer_size != size) + { + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_ptr->zbuffer_size = (uInt)size; + } + } # endif } @@ -1563,7 +1626,7 @@ void PNGAPI png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) { if (png_ptr != NULL && info_ptr != NULL) - info_ptr->valid &= ~mask; + info_ptr->valid &= (unsigned int)(~mask); } @@ -1662,7 +1725,9 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) png_uint_32 /* PRIVATE */ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) { +#ifdef PNG_WARNINGS_SUPPORTED png_const_charp orig_key = key; +#endif png_uint_32 key_len = 0; int bad_character = 0; int space = 1; @@ -1680,14 +1745,16 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) png_byte ch = (png_byte)*key++; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; + { + *new_key++ = ch; ++key_len; space = 0; + } else if (space == 0) { /* A space or an invalid character when one wasn't seen immediately * before; output just a space. */ - *new_key++ = 32, ++key_len, space = 1; + *new_key++ = 32; ++key_len; space = 1; /* If the character was not a space then it is invalid. */ if (ch != 32) @@ -1700,7 +1767,7 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) if (key_len > 0 && space != 0) /* trailing space */ { - --key_len, --new_key; + --key_len; --new_key; if (bad_character == 0) bad_character = 32; } @@ -1725,7 +1792,9 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); } -#endif /* WARNINGS */ +#else /* !WARNINGS */ + PNG_UNUSED(png_ptr) +#endif /* !WARNINGS */ return key_len; } diff --git a/source/Irrlicht/libpng/pngstruct.h b/source/Irrlicht/libpng/pngstruct.h index c8e2068a..a94de65b 100644 --- a/source/Irrlicht/libpng/pngstruct.h +++ b/source/Irrlicht/libpng/pngstruct.h @@ -1,10 +1,10 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -47,7 +47,7 @@ /* 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 + * maximum for size_t. The value can be overridden 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.) @@ -214,7 +214,7 @@ struct png_struct_def 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 */ + 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 */ @@ -232,7 +232,7 @@ struct png_struct_def 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 */ + 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 */ @@ -249,7 +249,7 @@ struct png_struct_def png_byte filter; /* file filter type (always 0) */ png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte 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 */ @@ -263,7 +263,7 @@ struct png_struct_def /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* pixel depth after read/write transforms */ -#if PNG_ZLIB_VERNUM >= 0x1240 +#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) @@ -307,7 +307,7 @@ struct png_struct_def #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit transformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ @@ -328,10 +328,10 @@ struct png_struct_def 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 */ + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + 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 */ @@ -353,7 +353,7 @@ struct png_struct_def /* Options */ #ifdef PNG_SET_OPTION_SUPPORTED - png_byte options; /* On/off state (up to 4 options) */ + png_uint_32 options; /* On/off state (up to 16 options) */ #endif #if PNG_LIBPNG_VER < 10700 @@ -392,6 +392,12 @@ struct png_struct_def /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ #endif +/* New member added in libpng-1.6.36 */ +#if defined(PNG_READ_EXPAND_SUPPORTED) && \ + defined(PNG_ARM_NEON_IMPLEMENTATION) + png_bytep riffled_palette; /* buffer for accelerated palette expansion */ +#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 */ @@ -451,7 +457,7 @@ struct png_struct_def #endif /* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; + size_t old_big_row_buf_size; #ifdef PNG_READ_SUPPORTED /* New member added in libpng-1.2.30 */ diff --git a/source/Irrlicht/libpng/pngtest.c b/source/Irrlicht/libpng/pngtest.c index 792bd039..de626384 100644 --- a/source/Irrlicht/libpng/pngtest.c +++ b/source/Irrlicht/libpng/pngtest.c @@ -1,10 +1,10 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.5.25 [December 3, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -43,15 +43,6 @@ #include "png.h" -/* 1.6.1 added support for the configure test harness, which uses 77 to indicate - * a skipped test, in earlier versions we need to succeed on a skipped test, so: - */ -#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) -# define SKIP 77 -#else -# define SKIP 0 -#endif - /* Known chunks that exist in pngtest.png must be supported or pngtest will fail * simply as a result of re-ordering them. This may be fixed in 1.7 * @@ -139,13 +130,13 @@ static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; static int tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t) { - png_const_charp str = png_convert_to_rfc1123(png_ptr, t); + png_const_charp str = png_convert_to_rfc1123(png_ptr, t); - if (str == NULL) - return 0; + if (str == NULL) + return 0; - strcpy(ts, str); - return 1; + strcpy(ts, str); + return 1; } #endif /* older libpng */ #endif @@ -153,6 +144,7 @@ tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t) static int verbose = 0; static int strict = 0; static int relaxed = 0; +static int xfail = 0; static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ static int error_count = 0; /* count calls to png_error */ static int warning_count = 0; /* count calls to png_warning */ @@ -249,95 +241,95 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) * png_byte pixel_depth bits per pixel (depth*channels) */ - /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ - if (row_info->color_type == 0 || row_info->color_type == 3) - { - int pos = 0; - png_uint_32 n, nstop; + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; - for (n = 0, nstop=row_info->width; nbit_depth == 1) - { - if (((*dp << pos++ ) & 0x80) == 0) - zero_samples++; + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; - if (pos == 8) - { - pos = 0; - dp++; - } - } + if (pos == 8) + { + pos = 0; + dp++; + } + } - if (row_info->bit_depth == 2) - { - if (((*dp << (pos+=2)) & 0xc0) == 0) - zero_samples++; + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; - if (pos == 8) - { - pos = 0; - dp++; - } - } + if (pos == 8) + { + pos = 0; + dp++; + } + } - if (row_info->bit_depth == 4) - { - if (((*dp << (pos+=4)) & 0xf0) == 0) - zero_samples++; + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; - if (pos == 8) - { - pos = 0; - dp++; - } - } + if (pos == 8) + { + pos = 0; + dp++; + } + } - if (row_info->bit_depth == 8) - if (*dp++ == 0) - zero_samples++; + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; - if (row_info->bit_depth == 16) - { - if ((*dp | *(dp+1)) == 0) - zero_samples++; - dp+=2; - } - } - } - else /* Other color types */ - { - png_uint_32 n, nstop; - int channel; - int color_channels = row_info->channels; - if (row_info->color_type > 3) - color_channels--; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3) + color_channels--; - for (n = 0, nstop=row_info->width; nbit_depth == 8) - if (*dp++ == 0) - zero_samples++; + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; - if (row_info->bit_depth == 16) - { - if ((*dp | *(dp+1)) == 0) - zero_samples++; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; - dp+=2; - } - } - if (row_info->color_type > 3) - { - dp++; - if (row_info->bit_depth == 16) - dp++; - } - } - } + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } } #endif /* WRITE_USER_TRANSFORM */ @@ -353,11 +345,11 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) #ifdef PNG_IO_STATE_SUPPORTED void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op); +pngtest_check_io_state(png_structp png_ptr, size_t data_length, + png_uint_32 io_op); void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op) +pngtest_check_io_state(png_structp png_ptr, size_t data_length, + png_uint_32 io_op) { png_uint_32 io_state = png_get_io_state(png_ptr); int err = 0; @@ -394,12 +386,12 @@ pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, #endif static void PNGCBAPI -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check = 0; + size_t check = 0; png_voidp io_ptr; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t + /* fread() returns 0 on error, so it is OK to store this in a size_t * instead of an int, which is what fread() actually returns. */ io_ptr = png_get_io_ptr(png_ptr); @@ -433,9 +425,9 @@ pngtest_flush(png_structp png_ptr) * than changing the library. */ static void PNGCBAPI -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +pngtest_write_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); @@ -457,13 +449,13 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) */ typedef struct { - PNG_CONST char *file_name; + const char *file_name; } pngtest_error_parameters; static void PNGCBAPI pngtest_warning(png_structp png_ptr, png_const_charp message) { - PNG_CONST char *name = "UNKNOWN (ERROR!)"; + const char *name = "UNKNOWN (ERROR!)"; pngtest_error_parameters *test = (pngtest_error_parameters*)png_get_error_ptr(png_ptr); @@ -472,7 +464,7 @@ pngtest_warning(png_structp png_ptr, png_const_charp message) if (test != NULL && test->file_name != NULL) name = test->file_name; - fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + fprintf(STDERR, "\n%s: libpng warning: %s\n", name, message); } /* This is the default error handling function. Note that replacements for @@ -541,7 +533,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) memory_infop pinfo; png_set_mem_fn(png_ptr, NULL, NULL, NULL); pinfo = (memory_infop)png_malloc(png_ptr, - (sizeof *pinfo)); + (sizeof *pinfo)); pinfo->size = size; current_allocation += size; total_allocation += size; @@ -571,7 +563,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) if (verbose != 0) printf("png_malloc %lu bytes at %p\n", (unsigned long)size, - pinfo->pointer); + pinfo->pointer); return (png_voidp)(pinfo->pointer); } @@ -713,7 +705,7 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk) * The unknown chunk structure contains the chunk data: * png_byte name[5]; * png_byte *data; - * png_size_t size; + * size_t size; * * Note that libpng has already taken care of the CRC handling. */ @@ -778,9 +770,9 @@ write_vpAg_chunk(png_structp write_ptr) if (verbose != 0) fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", - (unsigned long)user_chunk_data.vpAg_width, - (unsigned long)user_chunk_data.vpAg_height, - user_chunk_data.vpAg_units); + (unsigned long)user_chunk_data.vpAg_width, + (unsigned long)user_chunk_data.vpAg_height, + user_chunk_data.vpAg_units); png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width); png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height); @@ -821,7 +813,7 @@ write_chunks(png_structp write_ptr, int location) #ifdef PNG_TEXT_SUPPORTED static void pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr, - int num_text) + int num_text) { while (num_text > 0) { @@ -858,7 +850,7 @@ pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr, /* Test one file */ static int -test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +test_one_file(const char *inname, const char *outname) { static png_FILE_p fpin; static png_FILE_p fpout; /* "static" prevents setjmp corruption */ @@ -903,26 +895,26 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) pngtest_debug("Allocating read and write structures"); #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG read_ptr = - png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); #else read_ptr = - png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif png_set_error_fn(read_ptr, &error_parameters, pngtest_error, - pngtest_warning); + pngtest_warning); #ifdef PNG_WRITE_SUPPORTED #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG write_ptr = - png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); #else write_ptr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif png_set_error_fn(write_ptr, &error_parameters, pngtest_error, - pngtest_warning); + pngtest_warning); #endif pngtest_debug("Allocating read_info, write_info and end_info structures"); read_info_ptr = png_create_info_struct(read_ptr); @@ -935,7 +927,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef PNG_READ_USER_CHUNKS_SUPPORTED init_callback_info(read_info_ptr); png_set_read_user_chunk_fn(read_ptr, &user_chunk_data, - read_user_chunk_callback); + read_user_chunk_callback); #endif #ifdef PNG_SETJMP_SUPPORTED @@ -945,8 +937,12 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_free(read_ptr, row_buf); row_buf = NULL; + if (verbose != 0) + fprintf(STDERR, " destroy read structs\n"); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); #ifdef PNG_WRITE_SUPPORTED + if (verbose != 0) + fprintf(STDERR, " destroy write structs\n"); png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif @@ -961,11 +957,15 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) if (setjmp(png_jmpbuf(write_ptr))) { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + if (verbose != 0) + fprintf(STDERR, " destroying read structs\n"); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + if (verbose != 0) + fprintf(STDERR, " destroying write structs\n"); png_destroy_info_struct(write_ptr, &write_end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif FCLOSE(fpin); FCLOSE(fpout); return (1); @@ -973,15 +973,16 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #endif #endif +#ifdef PNG_BENIGN_ERRORS_SUPPORTED if (strict != 0) { /* Treat png_benign_error() as errors on read */ png_set_benign_errors(read_ptr, 0); -#ifdef PNG_WRITE_SUPPORTED +# ifdef PNG_WRITE_SUPPORTED /* Treat them as errors on write */ png_set_benign_errors(write_ptr, 0); -#endif +# endif /* if strict is not set, then app warnings and errors are treated as * warnings in release builds, but not in unstable builds; this can be @@ -994,10 +995,20 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) /* Allow application (pngtest) errors and warnings to pass */ png_set_benign_errors(read_ptr, 1); -#ifdef PNG_WRITE_SUPPORTED - png_set_benign_errors(write_ptr, 1); + /* Turn off CRC checking while reading */ + png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); + +#ifdef PNG_IGNORE_ADLER32 + /* Turn off ADLER32 checking while reading */ + png_set_option(read_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON); #endif + +# ifdef PNG_WRITE_SUPPORTED + png_set_benign_errors(write_ptr, 1); +# endif + } +#endif /* BENIGN_ERRORS */ pngtest_debug("Initializing input and output streams"); #ifdef PNG_STDIO_SUPPORTED @@ -1010,9 +1021,9 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) # ifdef PNG_WRITE_SUPPORTED png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, # ifdef PNG_WRITE_FLUSH_SUPPORTED - pngtest_flush); + pngtest_flush); # else - NULL); + NULL); # endif # endif #endif @@ -1052,11 +1063,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) */ #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, - NULL, 0); + NULL, 0); #endif #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, - NULL, 0); + NULL, 0); #endif #endif @@ -1080,7 +1091,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) &color_type, &interlace_type, &compression_type, &filter_type) != 0) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); + color_type, interlace_type, compression_type, filter_type); /* num_passes may not be available below if interlace support is not * provided by libpng for both read and write. */ @@ -1107,13 +1118,13 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef PNG_cHRM_SUPPORTED { png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; + blue_y; if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, - &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) { png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); + red_y, green_x, green_y, blue_x, blue_y); } } #endif @@ -1130,13 +1141,13 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef PNG_cHRM_SUPPORTED { double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; + blue_y; if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) + &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) { png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); + red_y, green_x, green_y, blue_x, blue_y); } } #endif @@ -1158,10 +1169,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) int compression_type; if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, - &profile, &proflen) != 0) + &profile, &proflen) != 0) { png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, - profile, proflen); + profile, proflen); } } #endif @@ -1190,6 +1201,22 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) } } #endif +#ifdef PNG_READ_eXIf_SUPPORTED + { + png_bytep exif=NULL; + png_uint_32 exif_length; + + if (png_get_eXIf_1(read_ptr, read_info_ptr, &exif_length, &exif) != 0) + { + if (exif_length > 1) + fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1], + (unsigned long)exif_length); +# ifdef PNG_WRITE_eXIf_SUPPORTED + png_set_eXIf_1(write_ptr, write_info_ptr, exif_length, exif); +# endif + } + } +#endif #ifdef PNG_hIST_SUPPORTED { png_uint_16p hist; @@ -1218,10 +1245,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) int type, nparams; if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, - &nparams, &units, ¶ms) != 0) + &nparams, &units, ¶ms) != 0) { png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, - nparams, units, params); + nparams, units, params); } } #endif @@ -1251,7 +1278,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) double scal_width, scal_height; if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height) != 0) + &scal_height) != 0) { png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); } @@ -1263,7 +1290,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_charp scal_width, scal_height; if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height) != 0) + &scal_height) != 0) { png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); @@ -1300,11 +1327,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { int i; - printf("\n"); + fprintf(STDERR,"\n"); for (i=0; i 1) + fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1], + (unsigned long)exif_length); +# ifdef PNG_WRITE_eXIf_SUPPORTED + png_set_eXIf_1(write_ptr, write_end_info_ptr, exif_length, exif); +# endif + } + } +#endif #ifdef PNG_tIME_SUPPORTED { png_timep mod_time; @@ -1549,12 +1601,12 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { png_unknown_chunkp unknowns; int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr, - &unknowns); + &unknowns); if (num_unknowns != 0) { png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, - num_unknowns); + num_unknowns); #if PNG_LIBPNG_VER < 10600 /* Copy the locations from the read_info_ptr. The automatically * generated locations in write_end_info_ptr are wrong prior to 1.6.0 @@ -1564,7 +1616,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) int i; for (i = 0; i < num_unknowns; i++) png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, - unknowns[i].location); + unknowns[i].location); } #endif } @@ -1598,7 +1650,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) iwidth = png_get_image_width(write_ptr, write_info_ptr); iheight = png_get_image_height(write_ptr, write_info_ptr); fprintf(STDERR, "\n Image width = %lu, height = %lu\n", - (unsigned long)iwidth, (unsigned long)iheight); + (unsigned long)iwidth, (unsigned long)iheight); } #endif @@ -1631,7 +1683,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) * above, but this is safe. */ fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", - inname, error_count, warning_count); + inname, error_count, warning_count); if (strict != 0) return (1); @@ -1642,14 +1694,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) else if (unsupported_chunks > 0) { fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", - inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); + inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); } # endif else if (warning_count > 0) { fprintf(STDERR, "\n %s: %d libpng warnings found", - inname, warning_count); + inname, warning_count); if (strict != 0) return (1); @@ -1676,7 +1728,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) for (;;) { static int wrote_question = 0; - png_size_t num_in, num_out; + size_t num_in, num_out; char inbuf[256], outbuf[256]; num_in = fread(inbuf, 1, sizeof inbuf, fpin); @@ -1685,18 +1737,19 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) if (num_in != num_out) { fprintf(STDERR, "\nFiles %s and %s are of a different size\n", - inname, outname); + inname, outname); if (wrote_question == 0 && unsupported_chunks == 0) { fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname, PNG_ZBUF_SIZE); + " Was %s written with the same maximum IDAT" + " chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); + "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); wrote_question = 1; } @@ -1716,17 +1769,18 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) if (memcmp(inbuf, outbuf, num_in)) { fprintf(STDERR, "\nFiles %s and %s are different\n", inname, - outname); + outname); if (wrote_question == 0 && unsupported_chunks == 0) { fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", + " Was %s written with the same maximum" + " IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); + "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", + " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } @@ -1757,11 +1811,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) /* Input and output filenames */ #ifdef RISCOS -static PNG_CONST char *inname = "pngtest/png"; -static PNG_CONST char *outname = "pngout/png"; +static const char *inname = "pngtest/png"; +static const char *outname = "pngout/png"; #else -static PNG_CONST char *inname = "pngtest.png"; -static PNG_CONST char *outname = "pngout.png"; +static const char *inname = "pngtest.png"; +static const char *outname = "pngout.png"; #endif int @@ -1777,12 +1831,12 @@ main(int argc, char *argv[]) fprintf(STDERR, "%s", png_get_copyright(NULL)); /* Show the version of libpng used in building the library */ fprintf(STDERR, " library (%lu):%s", - (unsigned long)png_access_version_number(), - png_get_header_version(NULL)); + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); /* Show the version of libpng used in building the application */ fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, - PNG_HEADER_VERSION_STRING); + PNG_HEADER_VERSION_STRING); /* Do some consistency checking on the memory allocation settings, I'm * not sure this matters, but it is nice to know, the first of these @@ -1800,7 +1854,7 @@ main(int argc, char *argv[]) if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) { fprintf(STDERR, - "Warning: versions are different between png.h and png.c\n"); + "Warning: versions are different between png.h and png.c\n"); fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); ++ierror; @@ -1836,6 +1890,7 @@ main(int argc, char *argv[]) inname = argv[2]; strict++; relaxed = 0; + multiple=1; } else if (strcmp(argv[1], "--relaxed") == 0) @@ -1845,6 +1900,17 @@ main(int argc, char *argv[]) inname = argv[2]; strict = 0; relaxed++; + multiple=1; + } + else if (strcmp(argv[1], "--xfail") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict = 0; + xfail++; + relaxed++; + multiple=1; } else @@ -1855,19 +1921,19 @@ main(int argc, char *argv[]) } if (multiple == 0 && argc == 3 + verbose) - outname = argv[2 + verbose]; + outname = argv[2 + verbose]; if ((multiple == 0 && argc > 3 + verbose) || (multiple != 0 && argc < 2)) { - fprintf(STDERR, - "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", - argv[0], argv[0]); - fprintf(STDERR, - " reads/writes one PNG file (without -m) or multiple files (-m)\n"); - fprintf(STDERR, - " with -m %s is used as a temporary file\n", outname); - exit(1); + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); } if (multiple != 0) @@ -1888,7 +1954,7 @@ main(int argc, char *argv[]) { #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED fprintf(STDERR, "\n PASS (%lu zero samples)\n", - (unsigned long)zero_samples); + (unsigned long)zero_samples); #else fprintf(STDERR, " PASS\n"); #endif @@ -1902,26 +1968,31 @@ main(int argc, char *argv[]) else { - fprintf(STDERR, " FAIL\n"); - ierror += kerror; + if (xfail) + fprintf(STDERR, " XFAIL\n"); + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } } #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG if (allocation_now != current_allocation) fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", - current_allocation - allocation_now); + current_allocation - allocation_now); if (current_allocation != 0) { memory_infop pinfo = pinformation; fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", - current_allocation); + current_allocation); while (pinfo != NULL) { fprintf(STDERR, " %lu bytes at %p\n", - (unsigned long)pinfo->size, - pinfo->pointer); + (unsigned long)pinfo->size, + pinfo->pointer); pinfo = pinfo->next; } } @@ -1929,13 +2000,13 @@ main(int argc, char *argv[]) } #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); + current_allocation); fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); + maximum_allocation); fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); + total_allocation); fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); + num_allocations); #endif } @@ -1970,7 +2041,7 @@ main(int argc, char *argv[]) { #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED fprintf(STDERR, "\n PASS (%lu zero samples)\n", - (unsigned long)zero_samples); + (unsigned long)zero_samples); #else fprintf(STDERR, " PASS\n"); #endif @@ -1991,25 +2062,30 @@ main(int argc, char *argv[]) #endif } - fprintf(STDERR, " FAIL\n"); - ierror += kerror; + if (xfail) + fprintf(STDERR, " XFAIL\n"); + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } } #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG if (allocation_now != current_allocation) fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", - current_allocation - allocation_now); + current_allocation - allocation_now); if (current_allocation != 0) { memory_infop pinfo = pinformation; fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", - current_allocation); + current_allocation); while (pinfo != NULL) { fprintf(STDERR, " %lu bytes at %p\n", - (unsigned long)pinfo->size, pinfo->pointer); + (unsigned long)pinfo->size, pinfo->pointer); pinfo = pinfo->next; } } @@ -2017,13 +2093,13 @@ main(int argc, char *argv[]) } #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); + current_allocation); fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); + maximum_allocation); fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); + total_allocation); fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); + num_allocations); #endif } @@ -2032,13 +2108,13 @@ main(int argc, char *argv[]) t_misc += (t_stop - t_start); t_start = t_stop; fprintf(STDERR, " CPU time used = %.3f seconds", - (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); fprintf(STDERR, " (decoding %.3f,\n", - t_decode/(float)CLOCKS_PER_SEC); + t_decode/(float)CLOCKS_PER_SEC); fprintf(STDERR, " encoding %.3f ,", - t_encode/(float)CLOCKS_PER_SEC); + t_encode/(float)CLOCKS_PER_SEC); fprintf(STDERR, " other %.3f seconds)\n\n", - t_misc/(float)CLOCKS_PER_SEC); + t_misc/(float)CLOCKS_PER_SEC); #endif if (ierror == 0) @@ -2050,19 +2126,19 @@ main(int argc, char *argv[]) dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); fprintf(STDERR, " Default limits:\n"); fprintf(STDERR, " width_max = %lu\n", - (unsigned long) png_get_user_width_max(dummy_ptr)); + (unsigned long) png_get_user_width_max(dummy_ptr)); fprintf(STDERR, " height_max = %lu\n", - (unsigned long) png_get_user_height_max(dummy_ptr)); + (unsigned long) png_get_user_height_max(dummy_ptr)); if (png_get_chunk_cache_max(dummy_ptr) == 0) fprintf(STDERR, " cache_max = unlimited\n"); else fprintf(STDERR, " cache_max = %lu\n", - (unsigned long) png_get_chunk_cache_max(dummy_ptr)); + (unsigned long) png_get_chunk_cache_max(dummy_ptr)); if (png_get_chunk_malloc_max(dummy_ptr) == 0) fprintf(STDERR, " malloc_max = unlimited\n"); else fprintf(STDERR, " malloc_max = %lu\n", - (unsigned long) png_get_chunk_malloc_max(dummy_ptr)); + (unsigned long) png_get_chunk_malloc_max(dummy_ptr)); png_destroy_read_struct(&dummy_ptr, NULL, NULL); return (int)(ierror != 0); @@ -2072,11 +2148,11 @@ int main(void) { fprintf(STDERR, - " test ignored because libpng was not built with read support\n"); + " test ignored because libpng was not built with read support\n"); /* And skip this test */ - return SKIP; + return PNG_LIBPNG_VER < 10600 ? 0 : 77; } #endif /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_23 Your_png_h_is_not_version_1_6_23; +typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37; diff --git a/source/Irrlicht/libpng/pngtest.png b/source/Irrlicht/libpng/pngtest.png index 81f5f8438a9f0fa8b87cd0266334f72792febf8f..66df0c4e6f6d13981148bf2fbb85df2b797028a7 100644 GIT binary patch delta 92 zcmezFyxnC&?PPOC#fde$Hb*c{Q}8rNjqptK^<~gvU|`^2U}6+vUgTe~DWM4fuPzH1 diff --git a/source/Irrlicht/libpng/pngtrans.c b/source/Irrlicht/libpng/pngtrans.c index 33ca1e2b..ccb9659d 100644 --- a/source/Irrlicht/libpng/pngtrans.c +++ b/source/Irrlicht/libpng/pngtrans.c @@ -1,10 +1,10 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -172,13 +172,14 @@ png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) * size! */ png_app_error(png_ptr, - "png_set_filler is invalid for low bit depth gray output"); + "png_set_filler is invalid for" + " low bit depth gray output"); return; } default: png_app_error(png_ptr, - "png_set_filler: inappropriate color type"); + "png_set_filler: inappropriate color type"); return; } # else @@ -268,8 +269,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i++) { @@ -282,8 +283,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 8) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 2) { @@ -297,8 +298,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 16) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 4) { @@ -344,7 +345,7 @@ png_do_swap(png_row_infop row_info, png_bytep row) #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -static PNG_CONST png_byte onebppswaptable[256] = { +static 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, @@ -379,7 +380,7 @@ static PNG_CONST png_byte onebppswaptable[256] = { 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; -static PNG_CONST png_byte twobppswaptable[256] = { +static 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, @@ -414,7 +415,7 @@ static PNG_CONST png_byte twobppswaptable[256] = { 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF }; -static PNG_CONST png_byte fourbppswaptable[256] = { +static 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, @@ -513,11 +514,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channel and, for sp, the filler */ - sp += 2, ++dp; + { + sp += 2; ++dp; + } /* For a 1 pixel wide image there is nothing to do */ while (sp < ep) - *dp++ = *sp, sp += 2; + { + *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 8; } @@ -527,10 +532,14 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; + { + sp += 4; dp += 2; + } while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; + { + *dp++ = *sp++; *dp++ = *sp; sp += 3; + } row_info->pixel_depth = 16; } @@ -553,11 +562,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channels and, for sp, the filler */ - sp += 4, dp += 3; + { + 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; + { + *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 24; } @@ -567,14 +580,16 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; + { + 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; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp; sp += 3; } row_info->pixel_depth = 48; @@ -594,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = dp-row; + row_info->rowbytes = (size_t)(dp-row); } #endif @@ -692,8 +707,8 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) * and this calculation is used because it avoids warnings that other * forms produced on either GCC or MSVC. */ - int padding = (-row_info->pixel_depth * row_info->width) & 7; - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + 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) { @@ -797,7 +812,7 @@ png_set_user_transform_info(png_structrp png_ptr, png_voidp (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"); + "info change after png_start_read_image or png_read_update_info"); return; } #endif diff --git a/source/Irrlicht/libpng/pngusr.dfa b/source/Irrlicht/libpng/pngusr.dfa new file mode 100644 index 00000000..d1b4d374 --- /dev/null +++ b/source/Irrlicht/libpng/pngusr.dfa @@ -0,0 +1,14 @@ +# 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 diff --git a/source/Irrlicht/libpng/pngwio.c b/source/Irrlicht/libpng/pngwio.c index b973f637..b6adfd53 100644 --- a/source/Irrlicht/libpng/pngwio.c +++ b/source/Irrlicht/libpng/pngwio.c @@ -1,10 +1,10 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.15 [November 20, 2014] - * Copyright (c) 1998-2002,2004,2006-2014 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -30,12 +30,12 @@ */ void /* PRIVATE */ -png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +png_write_data(png_structrp png_ptr, png_const_bytep data, 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); + length); else png_error(png_ptr, "Call to NULL write function"); @@ -48,9 +48,9 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_write_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; diff --git a/source/Irrlicht/libpng/pngwrite.c b/source/Irrlicht/libpng/pngwrite.c index 12f05aef..85ec5a46 100644 --- a/source/Irrlicht/libpng/pngwrite.c +++ b/source/Irrlicht/libpng/pngwrite.c @@ -1,10 +1,10 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.19 [November 12, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -22,7 +22,7 @@ /* Write out all the unknown chunks for the current given location */ static void write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, - unsigned int where) + unsigned int where) { if (info_ptr->unknown_chunks_num != 0) { @@ -148,11 +148,11 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) # ifdef PNG_WRITE_sRGB_SUPPORTED if ((info_ptr->valid & PNG_INFO_sRGB) != 0) png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); + "profile matches sRGB but writing iCCP instead"); # endif png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); + info_ptr->iccp_profile); } # ifdef PNG_WRITE_sRGB_SUPPORTED else @@ -237,6 +237,11 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED + if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); +#endif + #ifdef PNG_WRITE_hIST_SUPPORTED if ((info_ptr->valid & PNG_INFO_hIST) != 0) png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); @@ -383,7 +388,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) for (i = 0; i < info_ptr->num_text; i++) { png_debug2(2, "Writing trailer text chunk %d, type %d", i, - info_ptr->text[i].compression); + info_ptr->text[i].compression); /* An internationalized chunk? */ if (info_ptr->text[i].compression > 0) { @@ -432,6 +437,12 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) } } #endif + +#ifdef PNG_WRITE_eXIf_SUPPORTED + if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); +#endif + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); #endif @@ -458,7 +469,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_CONVERT_tIME_SUPPORTED void PNGAPI -png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) +png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime) { png_debug(1, "in png_convert_from_struct_tm"); @@ -666,9 +677,9 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5); png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); *(rp ) = (png_byte)(red >> 8); @@ -693,7 +704,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row) return; png_debug2(1, "in png_write_row (row %u, pass %d)", - png_ptr->row_number, png_ptr->pass); + png_ptr->row_number, png_ptr->pass); /* Initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) @@ -901,7 +912,7 @@ png_set_flush(png_structrp png_ptr, int nrows) if (png_ptr == NULL) return; - png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); + png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows); } /* Flush the current output buffers now */ @@ -1007,8 +1018,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters) case 5: case 6: case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); - /* FALL THROUGH */ #endif /* WRITE_FILTER */ + /* FALLTHROUGH */ case PNG_FILTER_VALUE_NONE: png_ptr->do_filter = PNG_FILTER_NONE; break; @@ -1069,7 +1080,7 @@ png_set_filter(png_structrp png_ptr, int method, int filters) * is not available so the filter can't be used. Just warn here. */ png_app_warning(png_ptr, - "png_set_filter: UP/AVG/PAETH cannot be added after start"); + "png_set_filter: UP/AVG/PAETH cannot be added after start"); filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); } @@ -1095,13 +1106,13 @@ png_set_filter(png_structrp png_ptr, int method, int filters) if (png_ptr->try_row == NULL) png_ptr->try_row = png_voidcast(png_bytep, - png_malloc(png_ptr, buf_size)); + png_malloc(png_ptr, buf_size)); if (num_filters > 1) { if (png_ptr->tst_row == NULL) png_ptr->tst_row = png_voidcast(png_bytep, - png_malloc(png_ptr, buf_size)); + png_malloc(png_ptr, buf_size)); } } png_ptr->do_filter = (png_byte)filters; @@ -1525,7 +1536,8 @@ png_write_image_16bit(png_voidp argument) display->first_row); png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p row_end; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + 3 : 1; int aindex = 0; png_uint_32 y = image->height; @@ -1539,9 +1551,9 @@ png_write_image_16bit(png_voidp argument) ++output_row; } else - aindex = channels; + aindex = (int)channels; # else - aindex = channels; + aindex = (int)channels; # endif } @@ -1554,14 +1566,14 @@ png_write_image_16bit(png_voidp argument) */ row_end = output_row + image->width * (channels+1); - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_uint_16p out_ptr = output_row; while (out_ptr < row_end) { - const png_uint_16 alpha = in_ptr[aindex]; + png_uint_16 alpha = in_ptr[aindex]; png_uint_32 reciprocal = 0; int c; @@ -1575,7 +1587,7 @@ png_write_image_16bit(png_voidp argument) if (alpha > 0 && alpha < 65535) reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; - c = channels; + c = (int)channels; do /* always at least one channel */ { png_uint_16 component = *in_ptr++; @@ -1610,7 +1622,7 @@ png_write_image_16bit(png_voidp argument) } png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } return 1; @@ -1624,11 +1636,11 @@ png_write_image_16bit(png_voidp argument) * calculation can be done to 15 bits of accuracy; however, the output needs to * be scaled in the range 0..255*65535, so include that scaling here. */ -# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) +# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha)) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, - png_uint_32 reciprocal/*from the above macro*/) + png_uint_32 reciprocal/*from the above macro*/) { /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 * is represented as some other value there is more likely to be a @@ -1683,7 +1695,8 @@ png_write_image_8bit(png_voidp argument) display->first_row); png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_uint_32 y = image->height; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + 3 : 1; if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) { @@ -1700,12 +1713,12 @@ png_write_image_8bit(png_voidp argument) else # endif - aindex = channels; + aindex = (int)channels; /* Use row_end in place of a loop counter: */ row_end = output_row + image->width * (channels+1); - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_bytep out_ptr = output_row; @@ -1723,7 +1736,7 @@ png_write_image_8bit(png_voidp argument) if (alphabyte > 0 && alphabyte < 255) reciprocal = UNP_RECIPROCAL(alpha); - c = channels; + c = (int)channels; do /* always at least one channel */ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); while (--c > 0); @@ -1735,7 +1748,7 @@ png_write_image_8bit(png_voidp argument) png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } /* while y */ } @@ -1746,7 +1759,7 @@ png_write_image_8bit(png_voidp argument) */ png_bytep row_end = output_row + image->width * channels; - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_bytep out_ptr = output_row; @@ -1760,7 +1773,7 @@ png_write_image_8bit(png_voidp argument) } png_write_row(png_ptr, output_row); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } } @@ -1770,25 +1783,25 @@ png_write_image_8bit(png_voidp argument) static void png_image_set_PLTE(png_image_write_control *display) { - const png_imagep image = display->image; + png_imagep image = display->image; const void *cmap = display->colormap; - const int entries = image->colormap_entries > 256 ? 256 : + int entries = image->colormap_entries > 256 ? 256 : (int)image->colormap_entries; /* NOTE: the caller must check for cmap != NULL and entries != 0 */ - const png_uint_32 format = image->format; - const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + png_uint_32 format = image->format; + unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) - const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && + int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0; # else # define afirst 0 # endif # ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; + int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; # else # define bgr 0 # endif @@ -1809,7 +1822,7 @@ png_image_set_PLTE(png_image_write_control *display) { png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); - entry += i * channels; + entry += (unsigned int)i * channels; if ((channels & 1) != 0) /* no alpha */ { @@ -1848,16 +1861,16 @@ png_image_set_PLTE(png_image_write_control *display) if (channels >= 3) /* RGB */ { palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], - alpha, reciprocal); + alpha, reciprocal); palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, - reciprocal); + reciprocal); palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, - reciprocal); + reciprocal); } else /* gray */ palette[i].blue = palette[i].red = palette[i].green = - png_unpremultiply(entry[afirst], alpha, reciprocal); + png_unpremultiply(entry[afirst], alpha, reciprocal); } } @@ -1865,7 +1878,7 @@ png_image_set_PLTE(png_image_write_control *display) { png_const_bytep entry = png_voidcast(png_const_bytep, cmap); - entry += i * channels; + entry += (unsigned int)i * channels; switch (channels) { @@ -1873,7 +1886,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[afirst ? 0 : 3]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: palette[i].blue = entry[afirst + (2 ^ bgr)]; palette[i].green = entry[afirst + 1]; @@ -1884,7 +1897,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[1 ^ afirst]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: palette[i].blue = palette[i].red = palette[i].green = entry[afirst]; @@ -1904,20 +1917,20 @@ png_image_set_PLTE(png_image_write_control *display) # endif png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, - entries); + entries); if (num_trans > 0) png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, - num_trans, NULL); + num_trans, NULL); - image->colormap_entries = entries; + image->colormap_entries = (png_uint_32)entries; } static int png_image_write_main(png_voidp argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; @@ -1927,7 +1940,7 @@ png_image_write_main(png_voidp argument) int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); - int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); + int write_16bit = linear && (display->convert_to_8bit == 0); # ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Make sure we error out on any bad situation */ @@ -1938,21 +1951,21 @@ png_image_write_main(png_voidp argument) * and total image size to ensure that they are within the system limits. */ { - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); - if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ + if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (display->row_stride == 0) display->row_stride = (png_int_32)/*SAFE*/png_row_stride; if (display->row_stride < 0) - check = -display->row_stride; + check = (png_uint_32)(-display->row_stride); else - check = display->row_stride; + check = (png_uint_32)display->row_stride; if (check >= png_row_stride) { @@ -1960,7 +1973,7 @@ png_image_write_main(png_voidp argument) * limits the whole image size to 32 bits for API compatibility with * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. */ - if (image->height > 0xFFFFFFFF/png_row_stride) + if (image->height > 0xffffffffU/png_row_stride) png_error(image->opaque->png_ptr, "memory image too large"); } @@ -1980,24 +1993,24 @@ png_image_write_main(png_voidp argument) png_uint_32 entries = image->colormap_entries; png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), - PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_image_set_PLTE(display); } else png_error(image->opaque->png_ptr, - "no color-map for color-mapped image"); + "no color-map for color-mapped image"); } else png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - write_16bit ? 16 : 8, - ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + - ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + write_16bit ? 16 : 8, + ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + + ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Counter-intuitively the data transformations must be called *after* * png_write_info, not before as in the read code, but the 'set' functions @@ -2012,11 +2025,11 @@ png_image_write_main(png_voidp argument) if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) png_set_cHRM_fixed(png_ptr, info_ptr, - /* color x y */ - /* white */ 31270, 32900, - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000 + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 ); } @@ -2039,7 +2052,7 @@ png_image_write_main(png_voidp argument) */ if (write_16bit != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; if ((*(png_const_bytep) & le) != 0) png_set_swap(png_ptr); @@ -2110,7 +2123,7 @@ png_image_write_main(png_voidp argument) (colormap == 0 && display->convert_to_8bit != 0)) { png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr))); + png_get_rowbytes(png_ptr, info_ptr))); int result; display->local_row = row; @@ -2136,7 +2149,7 @@ png_image_write_main(png_voidp argument) ptrdiff_t row_bytes = display->row_bytes; png_uint_32 y = image->height; - while (y-- > 0) + for (; y > 0; --y) { png_write_row(png_ptr, row); row += row_bytes; @@ -2149,12 +2162,11 @@ png_image_write_main(png_voidp argument) static void (PNGCBAPI -image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, - png_size_t size) +image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size) { png_image_write_control *display = png_voidcast(png_image_write_control*, - png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); - const png_alloc_size_t ob = display->output_bytes; + png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); + png_alloc_size_t ob = display->output_bytes; /* Check for overflow; this should never happen: */ if (size <= ((png_alloc_size_t)-1) - ob) @@ -2184,22 +2196,22 @@ static int png_image_write_memory(png_voidp argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); + argument); /* The rest of the memory-specific init and write_main in an error protected * environment. This case needs to use callbacks for the write operations * since libpng has no built in support for writing to memory. */ png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/, - image_memory_write, image_memory_flush); + image_memory_write, image_memory_flush); return png_image_write_main(display); } int PNGAPI png_image_write_to_memory(png_imagep image, void *memory, - png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, - const void *buffer, png_int_32 row_stride, const void *colormap) + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, + const void *buffer, png_int_32 row_stride, const void *colormap) { /* Write the image to the given buffer, or count the bytes if it is NULL */ if (image != NULL && image->version == PNG_IMAGE_VERSION) @@ -2251,12 +2263,12 @@ png_image_write_to_memory(png_imagep image, void *memory, else return png_image_error(image, - "png_image_write_to_memory: invalid argument"); + "png_image_write_to_memory: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"); + "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"); else return 0; @@ -2265,7 +2277,7 @@ png_image_write_to_memory(png_imagep image, void *memory, #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED int PNGAPI png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, - const void *buffer, png_int_32 row_stride, const void *colormap) + const void *buffer, png_int_32 row_stride, const void *colormap) { /* Write the image to the given (FILE*). */ if (image != NULL && image->version == PNG_IMAGE_VERSION) @@ -2301,12 +2313,12 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, else return png_image_error(image, - "png_image_write_to_stdio: invalid argument"); + "png_image_write_to_stdio: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); + "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); else return 0; @@ -2314,8 +2326,8 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, int PNGAPI png_image_write_to_file(png_imagep image, const char *file_name, - int convert_to_8bit, const void *buffer, png_int_32 row_stride, - const void *colormap) + int convert_to_8bit, const void *buffer, png_int_32 row_stride, + const void *colormap) { /* Write the image to the named file. */ if (image != NULL && image->version == PNG_IMAGE_VERSION) @@ -2327,7 +2339,7 @@ png_image_write_to_file(png_imagep image, const char *file_name, if (fp != NULL) { if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, - row_stride, colormap) != 0) + row_stride, colormap) != 0) { int error; /* from fflush/fclose */ @@ -2368,12 +2380,12 @@ png_image_write_to_file(png_imagep image, const char *file_name, else return png_image_error(image, - "png_image_write_to_file: invalid argument"); + "png_image_write_to_file: invalid argument"); } else if (image != NULL) return png_image_error(image, - "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); + "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); else return 0; diff --git a/source/Irrlicht/libpng/pngwtran.c b/source/Irrlicht/libpng/pngwtran.c index 834f678a..473c3b87 100644 --- a/source/Irrlicht/libpng/pngwtran.c +++ b/source/Irrlicht/libpng/pngwtran.c @@ -1,10 +1,10 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.18 [July 23, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -177,7 +177,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) { int shift_start[4], shift_dec[4]; - int channels = 0; + unsigned int channels = 0; if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) { @@ -212,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row, if (row_info->bit_depth < 8) { png_bytep bp = row; - png_size_t i; + size_t i; unsigned int mask; - png_size_t row_bytes = row_info->rowbytes; + size_t row_bytes = row_info->rowbytes; if (bit_depth->gray == 1 && row_info->bit_depth == 2) mask = 0x55; @@ -254,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, for (i = 0; i < istop; i++, bp++) { - - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int v, out; @@ -283,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, for (bp = row, i = 0; i < istop; i++) { - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int value, v; @@ -514,7 +513,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* 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) */ @@ -525,7 +524,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) #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)); + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); #endif #ifdef PNG_WRITE_PACKSWAP_SUPPORTED @@ -549,7 +548,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) #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)); + &(png_ptr->shift)); #endif #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED diff --git a/source/Irrlicht/libpng/pngwutil.c b/source/Irrlicht/libpng/pngwutil.c index a1ac2752..a479a682 100644 --- a/source/Irrlicht/libpng/pngwutil.c +++ b/source/Irrlicht/libpng/pngwutil.c @@ -1,10 +1,10 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.22 [May 26, 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.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * 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 @@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr) /* Write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)(8 - png_ptr->sig_bytes)); + (size_t)(8 - png_ptr->sig_bytes)); if (png_ptr->sig_bytes < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; @@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, * given to png_write_chunk_header(). */ void PNGAPI -png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, - png_size_t length) +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length) { /* Write the data, and run the CRC over it */ if (png_ptr == NULL) @@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr) /* Write the crc in a single operation */ png_save_uint_32(buf, png_ptr->crc); - png_write_data(png_ptr, buf, (png_size_t)4); + png_write_data(png_ptr, buf, 4); } /* Write a PNG chunk all at once. The type is an array of ASCII characters @@ -174,7 +173,7 @@ png_write_chunk_end(png_structrp png_ptr) */ static void png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { if (png_ptr == NULL) return; @@ -191,10 +190,10 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, /* This is the API that calls the internal function above. */ void PNGAPI png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, - length); + length); } /* This is used below to find the size of an image to pass to png_deflate_claim, @@ -291,7 +290,7 @@ optimize_cmf(png_bytep data, png_alloc_size_t data_size) /* Initialize the compressor for the appropriate type of compression. */ static int png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, - png_alloc_size_t data_size) + png_alloc_size_t data_size) { if (png_ptr->zowner != 0) { @@ -408,7 +407,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, png_ptr->zstream.avail_out = 0; /* Now initialize if required, setting the new parameters, otherwise just - * to a simple reset to the previous parameters. + * do a simple reset to the previous parameters. */ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) ret = deflateReset(&png_ptr->zstream); @@ -416,7 +415,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, else { ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, - memLevel, strategy); + memLevel, strategy); if (ret == Z_OK) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; @@ -477,7 +476,7 @@ typedef struct static void png_text_compress_init(compression_state *comp, png_const_bytep input, - png_alloc_size_t input_len) + png_alloc_size_t input_len) { comp->input = input; comp->input_len = input_len; @@ -487,7 +486,7 @@ png_text_compress_init(compression_state *comp, png_const_bytep input, /* Compress the data in the compression state input */ static int png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, - compression_state *comp, png_uint_32 prefix_len) + compression_state *comp, png_uint_32 prefix_len) { int ret; @@ -579,7 +578,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, /* Compress the data */ ret = deflate(&png_ptr->zstream, - input_len > 0 ? Z_NO_FLUSH : Z_FINISH); + input_len > 0 ? Z_NO_FLUSH : Z_FINISH); /* Claw back input data that was not consumed (because avail_in is * reset above every time round the loop). @@ -675,6 +674,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, int interlace_type) { png_byte buf[13]; /* Buffer to store the IHDR info */ + int is_invalid_depth; png_debug(1, "in png_write_IHDR"); @@ -700,11 +700,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_RGB: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGB image"); png_ptr->channels = 3; @@ -726,18 +726,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) + is_invalid_depth = (bit_depth != 8); +#ifdef PNG_WRITE_16BIT_SUPPORTED + is_invalid_depth = (is_invalid_depth && bit_depth != 16); +#endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); png_ptr->channels = 2; break; case PNG_COLOR_TYPE_RGB_ALPHA: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGBA image"); png_ptr->channels = 4; @@ -815,7 +819,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, buf[12] = (png_byte)interlace_type; /* Write the chunk */ - png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + png_write_complete_chunk(png_ptr, png_IHDR, buf, 13); if ((png_ptr->do_filter) == PNG_NO_FILTERS) { @@ -884,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr->red; buf[1] = pal_ptr->green; buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #else @@ -898,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr[i].red; buf[1] = pal_ptr[i].green; buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #endif @@ -925,7 +929,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, */ void /* PRIVATE */ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, - png_alloc_size_t input_len, int flush) + png_alloc_size_t input_len, int flush) { if (png_ptr->zowner != png_IDAT) { @@ -937,7 +941,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, if (png_ptr->zbuffer_list == NULL) { png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, - png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); png_ptr->zbuffer_list->next = NULL; } @@ -998,7 +1002,8 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); + if (size > 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->zstream.next_out = data; @@ -1044,7 +1049,8 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); + if (size > 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_ptr->zstream.avail_out = 0; png_ptr->zstream.next_out = NULL; png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; @@ -1068,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr) { png_debug(1, "in png_write_IEND"); - png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_write_complete_chunk(png_ptr, png_IEND, NULL, 0); png_ptr->mode |= PNG_HAVE_IEND; } @@ -1083,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) /* file_gamma is saved in 1/100,000ths */ png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); + png_write_complete_chunk(png_ptr, png_gAMA, buf, 4); } #endif @@ -1101,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent) "Invalid sRGB rendering intent specified"); buf[0]=(png_byte)srgb_intent; - png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_sRGB, buf, 1); } #endif @@ -1175,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_uint_32 name_len; png_byte new_name[80]; png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * spalette->nentries; + size_t entry_size = (spalette->depth == 8 ? 6 : 10); + size_t palette_size = entry_size * (size_t)spalette->nentries; png_sPLT_entryp ep; #ifndef PNG_POINTER_INDEXING_SUPPORTED int i; @@ -1193,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_write_chunk_header(png_ptr, png_sPLT, (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, - (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1)); - png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + png_write_chunk_data(png_ptr, &spalette->depth, 1); /* Loop through each palette entry, writing appropriately */ #ifdef PNG_POINTER_INDEXING_SUPPORTED @@ -1258,7 +1263,7 @@ void /* PRIVATE */ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) { png_byte buf[4]; - png_size_t size; + size_t size; png_debug(1, "in png_write_sBIT"); @@ -1358,7 +1363,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, /* Write the chunk out as it is */ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, - (png_size_t)num_trans); + (size_t)num_trans); } else if (color_type == PNG_COLOR_TYPE_GRAY) @@ -1373,7 +1378,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, } png_save_uint_16(buf, tran->gray); - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 2); } else if (color_type == PNG_COLOR_TYPE_RGB) @@ -1389,11 +1394,11 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, #endif { png_app_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); return; } - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 6); } else @@ -1426,7 +1431,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } buf[0] = back->index; - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 1); } else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) @@ -1441,12 +1446,13 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) #endif { png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + "Ignoring attempt to write 16-bit bKGD chunk " + "when bit_depth is 8"); return; } - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 6); } else @@ -1460,11 +1466,33 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } png_save_uint_16(buf, back->gray); - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 2); } } #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED +/* Write the Exif data */ +void /* PRIVATE */ +png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif) +{ + int i; + png_byte buf[1]; + + png_debug(1, "in png_write_eXIf"); + + png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif)); + + for (i = 0; i < num_exif; i++) + { + buf[0] = exif[i]; + png_write_chunk_data(png_ptr, buf, 1); + } + + png_write_chunk_end(png_ptr); +} +#endif + #ifdef PNG_WRITE_hIST_SUPPORTED /* Write the histogram */ void /* PRIVATE */ @@ -1489,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) for (i = 0; i < num_hist; i++) { png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); + png_write_chunk_data(png_ptr, buf, 2); } png_write_chunk_end(png_ptr); @@ -1500,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) /* Write a tEXt chunk */ void /* PRIVATE */ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len) + size_t text_len) { png_uint_32 key_len; png_byte new_key[80]; @@ -1571,7 +1599,7 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, /* Compute the compressed data; do it now for the length */ png_text_compress_init(&comp, (png_const_bytep)text, - text == NULL ? 0 : strlen(text)); + text == NULL ? 0 : strlen(text)); if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) png_error(png_ptr, png_ptr->zstream.msg); @@ -1597,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, png_const_charp lang, png_const_charp lang_key, png_const_charp text) { png_uint_32 key_len, prefix_len; - png_size_t lang_len, lang_key_len; + size_t lang_len, lang_key_len; png_byte new_key[82]; compression_state comp; @@ -1707,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, png_save_int_32(buf + 4, y_offset); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_oFFs, buf, 9); } #endif #ifdef PNG_WRITE_pCAL_SUPPORTED @@ -1718,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_charpp params) { png_uint_32 purpose_len; - png_size_t units_len, total_len; + size_t units_len, total_len; png_size_tp params_len; png_byte buf[10]; png_byte new_purpose[80]; @@ -1742,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, total_len = purpose_len + units_len + 10; params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); + (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t)))); /* Find the length of each parameter, making sure we don't count the * null terminator for the last parameter. @@ -1762,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_save_int_32(buf + 4, X1); buf[8] = (png_byte)type; buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + png_write_chunk_data(png_ptr, buf, 10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len); for (i = 0; i < nparams; i++) { @@ -1782,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, png_const_charp height) { png_byte buf[64]; - png_size_t wlen, hlen, total_len; + size_t wlen, hlen, total_len; png_debug(1, "in png_write_sCAL_s"); @@ -1823,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, png_save_uint_32(buf + 4, y_pixels_per_unit); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_pHYs, buf, 9); } #endif @@ -1853,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) buf[5] = mod_time->minute; buf[6] = mod_time->second; - png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); + png_write_complete_chunk(png_ptr, png_tIME, buf, 7); } #endif @@ -1865,16 +1893,16 @@ png_write_start_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif png_alloc_size_t buf_size; @@ -1941,7 +1969,7 @@ png_write_start_row(png_structrp png_ptr) */ if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) png_ptr->prev_row = png_voidcast(png_bytep, - png_calloc(png_ptr, buf_size)); + png_calloc(png_ptr, buf_size)); #endif /* WRITE_FILTER */ #ifdef PNG_WRITE_INTERLACING_SUPPORTED @@ -1980,16 +2008,16 @@ png_write_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif png_debug(1, "in png_write_finish_row"); @@ -2043,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr) { if (png_ptr->prev_row != NULL) memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth, png_ptr->width)) + 1); + PNG_ROWBYTES(png_ptr->usr_channels * + png_ptr->usr_bit_depth, png_ptr->width) + 1); return; } @@ -2070,10 +2098,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; png_debug(1, "in png_do_write_interlace"); @@ -2100,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 3); + sp = row + (size_t)(i >> 3); value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; d |= (value << shift); @@ -2138,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 2); + sp = row + (size_t)(i >> 2); value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; d |= (value << shift); @@ -2174,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 1); + sp = row + (size_t)(i >> 1); value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; d |= (value << shift); @@ -2200,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) png_bytep dp; png_uint_32 i; png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; + size_t pixel_bytes; /* Start at the beginning */ dp = row; @@ -2213,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) i += png_pass_inc[pass]) { /* Find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; + sp = row + (size_t)i * pixel_bytes; /* Move the pixel */ if (dp != sp) @@ -2244,17 +2272,17 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) */ static void /* PRIVATE */ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); + size_t row_bytes); #ifdef PNG_WRITE_FILTER_SUPPORTED -static png_size_t /* PRIVATE */ -png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { png_bytep rp, dp, lp; - png_size_t i; - png_size_t sum = 0; - int v; + size_t i; + size_t sum = 0; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2262,14 +2290,22 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, i++, rp++, dp++) { v = *dp = *rp; +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1; i < row_bytes; i++, rp++, lp++, dp++) { v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2278,14 +2314,35 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } -static png_size_t /* PRIVATE */ -png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, - const png_size_t lmins) +static void /* PRIVATE */ +png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes) +{ + png_bytep rp, dp, lp; + size_t i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } +} + +static size_t /* PRIVATE */ +png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp; - png_size_t i; - png_size_t sum = 0; - int v; + size_t i; + size_t sum = 0; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2294,7 +2351,11 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, i++, rp++, pp++, dp++) { v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2302,24 +2363,43 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, return (sum); } +static void /* PRIVATE */ +png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes) +{ + png_bytep rp, dp, pp; + size_t i; -static png_size_t /* PRIVATE */ -png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } +} + +static size_t /* PRIVATE */ +png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, lp; png_uint_32 i; - png_size_t sum = 0; - int v; + size_t sum = 0; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, - pp = png_ptr->prev_row + 1; i < bpp; i++) + pp = png_ptr->prev_row + 1; i < bpp; i++) { v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) @@ -2327,7 +2407,11 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2335,15 +2419,36 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } +static void /* PRIVATE */ +png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes) +{ + png_bytep rp, dp, pp, lp; + png_uint_32 i; -static png_size_t /* PRIVATE */ -png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } +} + +static size_t /* PRIVATE */ +png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, cp, lp; - png_size_t i; - png_size_t sum = 0; - int v; + size_t i; + size_t sum = 0; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2352,7 +2457,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, { v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; @@ -2381,7 +2490,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif if (sum > lmins) /* We are already worse, don't continue. */ break; @@ -2389,6 +2502,48 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } +static void /* PRIVATE */ +png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp, + size_t row_bytes) +{ + png_bytep rp, dp, pp, cp, lp; + size_t i; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; + i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } +} #endif /* WRITE_FILTER */ void /* PRIVATE */ @@ -2397,12 +2552,12 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) #ifndef PNG_WRITE_FILTER_SUPPORTED png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); #else - png_byte filter_to_do = png_ptr->do_filter; + unsigned int filter_to_do = png_ptr->do_filter; png_bytep row_buf; png_bytep best_row; png_uint_32 bpp; - png_size_t mins; - png_size_t row_bytes = row_info->rowbytes; + size_t mins; + size_t row_bytes = row_info->rowbytes; png_debug(1, "in png_write_find_filter"); @@ -2443,32 +2598,33 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) */ best_row = png_ptr->row_buf; - - if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE) + if (PNG_SIZE_MAX/128 <= row_bytes) { + /* Overflow can occur in the calculation, just select the lowest set + * filter. + */ + filter_to_do &= 0U-filter_to_do; + } + else if ((filter_to_do & PNG_FILTER_NONE) != 0 && + filter_to_do != PNG_FILTER_NONE) + { + /* Overflow not possible and multiple filters in the list, including the + * 'none' filter. + */ png_bytep rp; - png_size_t sum = 0; - png_size_t i; - int v; + size_t sum = 0; + size_t i; + unsigned int v; - if (PNG_SIZE_MAX/128 <= row_bytes) - { - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - /* Check for overflow */ - if (sum > PNG_SIZE_MAX/128 - 256) - break; - - v = *rp; - sum += (v < 128) ? v : 256 - v; - } - } - else /* Overflow is not possible */ { for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) { v = *rp; +#ifdef PNG_USE_ABS + sum += 128 - abs((int)v - 128); +#else sum += (v < 128) ? v : 256 - v; +#endif } } @@ -2479,14 +2635,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) if (filter_to_do == PNG_FILTER_SUB) /* It's the only filter so no testing is needed */ { - (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); + png_setup_sub_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_SUB) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); @@ -2505,14 +2661,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Up filter */ if (filter_to_do == PNG_FILTER_UP) { - (void) png_setup_up_row(png_ptr, row_bytes, mins); + png_setup_up_row_only(png_ptr, row_bytes); best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_UP) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_up_row(png_ptr, row_bytes, lmins); @@ -2531,14 +2687,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Avg filter */ if (filter_to_do == PNG_FILTER_AVG) { - (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); + png_setup_avg_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_AVG) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); @@ -2555,16 +2711,16 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) } /* Paeth filter */ - if ((filter_to_do == PNG_FILTER_PAETH) != 0) + if (filter_to_do == PNG_FILTER_PAETH) { - (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); + png_setup_paeth_row_only(png_ptr, bpp, row_bytes); best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_PAETH) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); @@ -2589,7 +2745,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) + size_t full_row_length/*includes filter byte*/) { png_debug(1, "in png_write_filtered_row"); diff --git a/tests/flyCircleAnimator.cpp b/tests/flyCircleAnimator.cpp index 272dd895..b976d313 100644 --- a/tests/flyCircleAnimator.cpp +++ b/tests/flyCircleAnimator.cpp @@ -48,7 +48,7 @@ bool flyCircleAnimator(void) { smgr->drawAll(); driver->endScene(); - result = takeScreenshotAndCompareAgainstReference(driver, "-flyCircleAnimator.png", 100); + result = takeScreenshotAndCompareAgainstReference(driver, "-flyCircleAnimator.png"); } device->closeDevice(); diff --git a/tests/media/Burning's Video-2dmatFilter.png b/tests/media/Burning's Video-2dmatFilter.png index bdd17cd18c57daefd78b3016b231161714c12d59..09891c8e60424c3edf228e2f1fa2c1ea3e741e2d 100644 GIT binary patch literal 18757 zcmX6_2RK{b-;b?EMXME~HL7aWE}_({JyW%3?Y(QqtQmW+P#UU)qM# zv4#Ba?|tv{hzHMe&b{ZJbH1N-BR3EzhK z4lyy4wgDw%0^s=1XSHo5L#b_6ZZ*5o4V3F(HBxqYQc`vh=oTq)1n5bGiWZS5h;xne zwq1AUxKy3tuV7iw_XsL*BqdP-<=y0XFg^W_>*XKKE=#u)-H|;@{Kt;0utzk#(T>>K z7o0vIQZPtZo|K&(1O`P#fS*K=t4$ncCh^3B^ltNv1)~4WY&{1(e@_pJ0RQAa7wSB( zTc?N+rjffoTN8p`Eq_eta5Xae_n4hg4a7+=Y!{&%3yKjTPD^7EmBLc7E0Ll;uOMMm z`5Zrx*bd*V`Q|R%%`^`2c#t^bcSS*K1d%-FD};$im_Di1V|H5_PSJjZ$OxTG@X_D! zixNUGYKhn@fs`|Y$c`ow!SR($?m-#C`%M~0#_$_3HT*l!CT<3^7mB?{Oe`#n9e5~b z>vWzhf)MHdnX%mY(e328&#bY_694V+%~f}~YO0`qGw>1%_zTg=)$%@q?414JNQ4Ne zNDabe2eN~T#ZyHXq$qyYz;=sA-iTU3FL;I#=;YWz#3Ud}A)cSiwRgZ+e3?KEgWwWQ zQ`*u}+0{MS_S{Cf#(n-D1>80dIk4gi>IOpCp*oZ zgsZ)<^ktVL*tw8JPwjh6!v~``m~7STK(u8FdJ%}X26iB(3~FW82t<0kb$7ODKB8Ng z^6(eCC@3$$>T8lx5ljkOL>U7XV#0J_?Pov9<(|?p_N#EjTxE-pGfH>x|GQaTC?zLw zPV1x`%X7zBK6cw4uIl10N*k*na(N4W*>yd7ZdLG3(5R<~jFp500ivgz0IyRPaDdru ziZvA6LXO;ry)d?5ovC5HWA9!pKK5;N+w8_NpmXnr>jnw^vJ9J^cF#| zC4*j$eNoZ|X$>Z&OwDx%s`FOQ*fb!=-q5nhmvb0r?&^N2jl`PdSeV;*k2MO2Dfg#w z5EI+dh>}>-@QjTA!57hpSSy!4@mA^A%h@0o&xP@8|1mnOEE>r@%ZAl%T?3Qbq9=lj zlvx=i9zmbMVH*o(azQ10;!uhe`L5^%G$*3+ErJ}K%-#D*q91~qwiDHEGyyZb0~g(J zJu}I9v&s+=Dz{QZBG2%=e8Nebnd4Q9`CUb0eHHyIu7ow{NimoD7hz@PS%1t-S|%-ANND&O(*{wvOZFns#ogp(OBc@|bs;oLaq$4Wu}w0LZ8&ZNcsW|TFQ^(J|=xb{w-iZX0? zdU_g~@^6WuM;uiOy#{^Cx0g% z4A^gNjYjR2OP1u%@0@gmoYq>jnN~lM8BZ$vd$2YTu=|UNhTQP30+>_*JaBM*-Fffm z!}JGm*`mkZ-kztY=d25+Qnv(IRAfvvXEXIW37WF_kl^+g>gL|Tbx-si#8G3Tw?|yN z(fPw%(J~`(7ANPotdVg)R&BND327QfI<{v%=H^zO7oA4N-)br=D+BhH!V(BrIYP@u zfJL*h0J#GA`NZ`#9Eq*nn)e9v@oDJl>S}C!fi~=lB23;f=OZ(!b>k!Jy;f6e3h=Ks z#Zl65W{6~}Gn^GuoTf50U@#ZSEQPhz=sSG2!5w-ZD^+zXNrj7JOF|F5(T1HtI2E+v zLw3=a__(+@;CJd^hFbF$7evthN>3acJn(dP@gVTm*0K4lg^5Ykv`hKK-`&MF(8s2x zCJe?NAq9n=9Zl)({5{=Y?Y+7Rdm3j#l&yjCX+gxJU|t);Ifmk_h#2b-qh?qC5xV}o zA?Qu2O1j;9V*N8S%#xlS(zO!gV0q`Mt+=Rr<|_oJF{`jK!uFilNLO=!`w(Hyu|%6Y zGxtpHa$5{!Y-QCoI4&jG|6d)zjmw265L|ygAc~+Q4tI6c<_-2*USn-;nlUSUxkaHE zF(>e1_~|p|cj`+{S#=f*htx$h>`@$$)HMY;SsBQ!34wyJlR3wQ1@xSo0|jTBtBjP? z`G!z<(ACAUxb~EI81Vd+CGcP`FKb89ah%6e`PHDzKJjt-?Eu1uR>mT0jH0^IYs=y;ncOD65_jv9q5&Gc)6_tGPS>2#av#Z2>E8 zP{tG~=*7%9VDx@yJT%>GZ1k{2eZY`|NI$i`fdXqRwNYRM*FLo=6S%+f_wRdi!Q7FJ zRj)ulzaJjWbrx+ES^xZ`r(It1+Sh?&SI^IbSOEGTc-SyIB@_$O;OO?2 zDpPQPtff47lcsT7@O*ZJpa0Ftkd&jTTGKisO`&u@%5`NPbgY`jL*)YR1F z=^op?doTHb=^_fDxk*R2uyf*C*Ws{N3#$rEx8n6rX9Eey*=lJ7%~3g+N302R&`$`H zr(_|#(fa(t%=c7lYjgh5vWYlq`SyVGht)UKV((BbU8p?dVM2+br_Y0gQf&FzjkkYi za!JYVtOt3J9sQjsx2&6W5^rj5-qBb;I`We!+z5ih;rCKb^*N%;I{O64Vjrc2g_|RVK z?rf>GO>=t0>!+R|Ytj7stgHjx|AH*5G5;<-svyE`UE=@nq5J3Mx5wHwP#=B$drz-| zJ6<7X3cxlk-Z9ij<4c_kE>%_4=$@57qlI0^W?j>65=MrG@Wad!gvx`qnU9wv8`xZ{ zI>YMlv$*iUwf^Ksy2xKGz5}>+vu2OQR{yPw?{z<3g0qYzL;t5#56Y>p$-3op+j~VTnSkj@ma7>PKjaupZjpxX;hax(0l!y1mi0#b82I9{q?YmaDBN4d@L}>>H zPnBGMTJ!+c)PMc$wd2Ns{(uz@lq(R;gf#DjH2%<>HZHSqj6GrW#7RRwN~|9OdJrY9 zU%8Y1z*jJkRrO7GZUzUjSrMOk`^98j9Hl;kzjQII>QjBae%-7qW`1mJY`Pj4;tzY5 znwial-5XluAjSAs^=ir}n7YO$RHxqf)1~HsHweN>!Y<#mG9DMLUMZ&bO6(UBOwWiA zA^#fBo{XD18O%j^5dUx__GI3vC9@)kNluYzQ4*c6t`4n;A>on9av zA>QtKbg>H>ZR;sjybx_{{%NDm zmk$(i-epSzQHs@~+zh%2az^juf(7Jqf2G5y1O>V}K6ZS`J-`NCPvc)}rK~||lxz_j zaV=^GocJVs?!s4m?VqmSQRGZ(FpY6vFk;5V+ab#OjsPn!>(c`nM(}T+-zG)x#yrP^ zm*RSDIxOj;y8SIcABl%?zdZ7DfE82eTp&oMoOHVxrEH16lluW98AXW@i`CNDY`s}F zp+X|+I;@O%oA%|-B)wuH z`3`mUTAe}KnMV!T zo2U}*IlH2#Fu3=PFnwu|H6o#GFxVsa)Il<3Mu860IJf=x?;uWQEU0VQO2>Bpi(fpo zYoXQs$UolC-{)_1d1G1{V0^hVGkh8wtK#}p;B+x__Z;}vQ_qW~B02TPUENs2>n~kx zUW^VBg>xhXRIKID-sLlF`|K7ks*~pcm3-~`<77*cNcrP;!3ah1Y?p(Ro!LyTTtx$x z$YGq9w2|=I=O+E@;^nS~&wGyT-|FQd$`6FCmU-HR!2&4e|C$!sLEM_Uj}EaEAE><(Bq@)Rkr`MB6Kwt{t;iM z$D`HXc)(+2CA4DR>sLQ+u`U_=8*0h-^WRzZxe)W;E~DEsX<*83c8L5Mw9K-O&mKf+ zGP6aiQqF683&a$sxKe|jl?v`=*Ur?bWKktgAAkC>m_|seUo+aCX2<;VFS5r^e;;D) zM1$~W-pvbdtjy$-QshD8-eXqPM#oWvc1Z~BBZNB0nkK5OE!IEwzNp&N`X^tc@>ef- zDfLm&KWe-dufL5iUQ`aG#hs~|djHDk!0PpF;gUe22+)m)7;qnqo)RwBBXlb~BjLZ)UwvWhjj;UPOl3iC9a^6xv|NvG@^v&hc_NSz zZr_+Bpv>}ElQPD+;JN-kwOQ}LTaSu$0z_}zv!r-s$DS}XCm?v2B}O=3YhkB$Mk0@F zJL>Mrmx7%>``Jl+u1|fv(8#n8nAFwPb;BoLJiTVa6 zN6;&=>w2yDvIPizQ{8p$lVMdNpiaHV zjb9SiK84J%q$;AFBs8Uqcm0^@MTk9Uv?}!57L&_=LByDob#=!DX_~2tdZ?opV0TA! zJ~AZ2hFe$M1FB}X_Bt{fEzTSJD?-($`J z(#7=N?6tI7mHLKz9ec+ZF+YQ{g<8Z*A`6KFH2F72ChIKXh$VC&@+3`|t}j zfBJ^3`KN=8%g#Ns%x2;S3L1dgO>O>=mQL*Zy}P@c%p&Qr+}Y94(15VK{C#Zo`HfWj zy-Jak%oBC&rz!2JB9R^}9yEw}d%*K+S*~@k?g+OvDoMOgOt{s38b}^?iJPJ(JqyQvdVWvdUOd-j*_gNvU`B zXreq?2U`@8tLGSyvNg^9a;$3??;o4G}HJH0@sY_VykGy3zH@j+|kaACRU7Ct@hV?eO8aB0j=>!J(H4p_AGhroB!3TdPGD&h*K;!wtT2uRad&$ zm)%exhw4pKLHU>GPr5RegIRM^KKxfcx;i`I8^hWE0c*qRuzY@7sdwSD?wxd&0xI;B zS(9tt5LGDCz(&EclQ>>6ZV)J?8k02(_lo^5Og?C!V792>nftdlgBmC&Ci`ugfT@M@SS%O>?b1`4LoLJakn(#8kob5Ah#h<@(h#hZxynvD|K5;) z!zb+&?SYWpJ$=op!SO}E3K*>h=}^l7nyF730%8FV^DB# zFdXhto}ZGEf|LmYW^q|o!&LU7hXyYyi&3`NiuYbrONsYxHaCgJgkJ{DWlooAEh$!? zs+1@ag!`t|e-Ox;!=FsnB|#ql2j9E;{cu5j_L^n+G#9|<%eZ!6;$2-`0UQl`p0V7Y zug04@R+P(i{p8f4jgH&AhK&eBNn~7L7Y)y|Z#AYF&VJQ=`?eFQeE*HWjK4kB4VZ=Z z)BJFD43e5hdkWsQ7h)-%L{vKA^s_c0UO~^;%&c(KVdr(*qK7M*O%5I!8fsoWT|>Af z$g}sm0WUSnICcp3Ui}c0bbphKAUW6b!=*v0XFJf>JN+yw0iU zE43piAo)415$A9lU*9S3qP4ZP?Cd*FBS#$?*(rf#h9T)^675eL#o{)GJv(8a|GJpA zCn+Z_Jtf?HyTO*)%cBvUVO5p$`7be;=$5cjp5XZi$_4%2ou=!pm&8*k=Sp=`z8tJ= zMg#uW=@lCNc-B7`52z6#`Qf`?%(t7pR&RXVe{C#Z6u#nW;*fw+rYs4`ydlpbOY69H zP_x8iRBbqXuLlftCBh4Aj1q0>h+qb19LX|k&T9XzoEHE z?9T3PZEfwdkdtq?c6LfY<#-eWNDg%de3?U}V5nn}xAL>Da4x&}LCS6reO{0-t0*~C zx2hg*U4G}!K51#P$>FRE0Atf=ZYktAM)&+UtgD?VoBRHUrQ@qrmB9I%z00RhpK4w! zzV+H$k{vtm?^nT?V(?n*Yf+U~N|ff{EmdJn>e$(o12@52LPJ^MGibkZ?4e~y~U|C*5XCVXvnOrh7jXG zfio5?JzfOUGWQPFf^Q6h=%?(;piH!m5$)!Jcd1f1M46KvKw4FyGT2jQeoUYQF>${! zYu`9hHdE1jMU^9F4O+X^WQxu`GXpR`oMmbV(o8~oTT7z{NwV4Ur-D&8<$qslk zt$}!;0Wt$PS&oOoT*`Lc4+CV!{Vm3z8Ka7C%_C>z2SNJIld(*SAhpRFIZE6&(!Nr2 zUMG8ln|2V}UupS*XVufgCT8prTTqkxC9KUvh?OGWT1@&RF9TJl)kj{&y^hnRxw*NX z9)%39tAm7#IVEC*PMdhrt_wig|j$SXP4KlbQpIc4BZ3yL8h>!o~zbHQ1Yl1|@ zimAtVXB~%RCLdRkcHH5TA+gw3h{q*(wh?d&YJ z2l?9C+V*sHG?-FTy}{z2E*z_jdjHBjyZTZ@aNU0$FFtg6CBii5E82e)yk-L7?SuLb zt^~3+FNAgfa*`U~uX3xwNXwcKw z)YY}sZb8RRPEMZgwZ9O!o5=-;l%DMeDjk*qtd$0QS7UqEDMo3>E-xv2py9Yt$s5N@ z*%srcQfu+w-=o_vlLMkk4L&gBuXm?`ro{J7xnp_85vxC*vW+{4q0+<#AQDUij~<0t zw}`ljCXBbOIp>X@`$C_xpd|+Mv(yLBhWr3Di{?r|=xbg(_&y#_hzGV?*>PW10AXQw znwM`zb)T$AE(HSGzw!0*)#CC2l@1zq$6UDI)A)LkAGtSrUY#7!b)Zv!R>US4e(&*b zsN5D!1iSVf$H3ru-QNP^JycH8+NmjH_ZTybtIaVB(W}CL{&L>PUJDBF3H_1uTaT&| z_Bb5-bXlh{X7K(6GsxJ&J=oIQ-{0RI?Tk|dBpI}x8~fLjlh;)S4L55}m%?&CSLN_$ z`1a4a&emp+yqWovgAIBuUu*QQ*<*JN>sZisqOH7hi; z|Kkvs)HCS-^Y{m7pXp~z2y%K=x`b*(aX{sOY6ldl&O4Gl9ME}HES{7=!wKLdCyByN zwi;kp1@`arGSYVp?^}&BJ|+HmlUqz1<&I;f2Ia z&4M%U#BMfLR)QdJq@tDxcx8T#+sRsKJv`r#&!m(pzBp^e@W~dxVT#g>W$GjESXY3P z=56l=Z}@BiT9ygYl*oiEcO=_1xj_Jj&E(I70b7y_#)U3-c%$LinIWmKqeHgWV2;;k zO#frDVKwaWg+hi)@X}WXW2`AVs?za#KMg7fiOeHZ|FD@Jwex ziC*?%#)cL@j%q+{GhAbV${U z0_MY%r07N0rxHYc;o?-4Yj&c@R%A;nqxniRe3KEd!eG}_*U3qEnyqBOFMvnN@m%zg zby>U)qm|7Y1oLuoDJpy5NZdq;nUqOI6WJ-`iEZN})VIz!IfMh-y>8+BPPkA5O((GrIdPuxo64#X9DLah9Wt+woh_hiENgAx`SRl z<3DE`XvuA~JhVI-nVD|e{m~(@g@8GgY(?!7LFwRlk)y%>3TBeh8(ADT)kZLPzE#r@ z2@rEQ>1R6R%Q&azLE4NHR5>1e>=RW>C(56(DmE^Y|2n zY0CZp!3vCL-vJ9q_w?O<*H;)T0{hyd(j#gcCqa&&k7}xNe-DaJx3LCGI~JRWBV)-p zxq=he+$Tpf*sy(`pJB19G8TP@0YJ0Q!T^K9n(n6MkeqH5@#jH8y9vBE-K|HqfqWQU zs6uiJqL^$AVIq(DF7>p{jcn~?EQCzXc#tgOr{eGUZgbrn4NjwTKWS>>S==uijyK%` z|JLHMuL9c8-?cG;GQyxLOB40m`g_T!Lwt=X8lbMPXE2=HEKhsgdL%>G)eJXM)~9`f z82b4}$-JVa9J%Pj816d~4=IR^dZj5)*+H0M08v=zS+FTjdv_Pal0G8H>I4L_Z`6UFbH>Gg90%yLhzXF@sL+RvNgl+@52T_bn($5UEVWzOc{T*j@aEHS z{2pP`=Z?Teto?Jleh6twd@K#I5<_3v!h8*v`uxsK7Ytw-w}%tbMAVh7lcX~o5Tr&L z&*S3}O--g-Tduk#_x;+ihuM6coz-5_=)dIo?9XK-zvpO+d^ z4{!YL2vJ2OYzVj_e$&M01>NT$Ui*Z>w5+Rs1^OJ`7|vK8>wMjVp?T3TvI*;1_He&n zQaoU@?OV%BUlh9jayQ3f_i1ale?WgpjQC3pF=2V-_qaI}pD|cvlD>#qbUtmAP9FUP z8zshWBF^)Amq~&TeJr68#S1QvLO#?b#nH#6P2^&ilVb%KCik-z%SFtmsAdz zZE+s8wh8@awnr)?k6uYBPtr$eDit8=ElgN?rLYK%K5I`;Ggpi1Tzc(#W3M8TF(!J5 zQhc7h)EW;d9~r{t?TXNONC%rbZ*x=AUA&a7xyGY$G2Y@0WfBlf8ey}-SioN$J&~2s z-rXXqCHmr4naw##qv>mAZlG72X124 z@K*9sv(TFpaKs{=Dg)d7Svh8dLA%7wV$SN}2v3lky=iOK01y6^%EwZU%-OD!NDH znQ)|&_!rQKNY-S)JtV*VfG#Hpb#Gv`DDh!ub2BaFv5K?I{mV`))Ko*1JWI66fB~ze z7H1zH-?=ArPBW@x>rl?hSD&a;jgyrcyxKSDUVWNinL0K@(yzk^KG2oqx&=gSf+`;g=zS+KVXAK zv!~H$?b&1C8BD;P>n%eKtn{g=DK5vRRR-HdO}e_e?&g{pQwxBo&9WHP z?e1)EySclY$t?qJ3<|dSdfd>c5X2ty*H4GZHd|vFXYTO6v!S7-!(L)0w5NAdn7Y>i zWhz7}$|C(HG|boD-QCyN=fM;B;kh+bbXb_w9FUskf0-YSJLp5kK4d3i&qt?$8_U_c z@P+GIcC;E*KglY<0Y2um>olyzFL?f$d&ym@Hx9n;L*YB~(+|6{4*yM8XKQQ#>gt?1 znfzE#<&+KLW%bK(-~5V;;o+H+91|fK_;%`x%#OzjNN%0>Y4$B2MgE~)LejnjY znh+ak0xgp~FiznQ!|M%9oqse-m}P4`enB-z*;8w|xUdAz?>Zn3Z#3ZB-QEU3O7l{y z`*|*T>&o)&C~6KA!^yWU1HR;o=>FkhLxv!-@s>fW{YIVLyT6Y|v;VOyWJ(dli@sW^ zionR-Y|H(({yavBgF3D+jx$e&)K~2Q^%pZIaCYDEmv0CAifeWChKsWdbNlrLi+V<% zepLJwd@osY$=t%?iAwm{s_NRrS$XQSU~F-~qi#Llb(uX@N%l=Y@NYdFw|0bdYucI(MN`p)a8G?fyc zorNLa95^^d$6COqRl9TfYb|CAPiwJag6*a248*H#ztZ7)Kb_DW*Yji3i^&=fKNi+b zc>UNrwwU#|m^}>}*$V#g6F-$q#<8>-b`L>*K7qZ{kPXMLa^}qZBw|>g~E3iv_-hPqh~-l z?1msed`mRbZc2IhkS|C=bb=iV68OxP{?f(nTbLAJJIo-{7sSBG~o|E!jxsCgf6zjaU98qddEP04d^FH>tY}P>GF&m@+3A0G@3N#gzr|U zh}unxbI5ZSLyc4`9U0FolvmYE1nV`GAz47_O2JjHFNP8)80d~$~&N+FIF2Hv3Ly=>;@hj z1xn-KNZX*8jGq#}#LrC>Et~C=+?8o=fmvNKGq@#H{$xJ3flzU<&RQ6LkW^tQ$4nsB zM9*J1+u#27X(kA1Z^DiGcw)(Sr_QRYv#CiUUn{ORGC5qLAGBg8T5lr=ggqVeXH0n9?D58(ZR{&!h8g2(nShrAS5OQC8rk@6mgEl_dyUP(=8K*H#R(s zctFnc{V+4{)Ca+ZEkn@BlhklqKcG|OT(>0%h$`iTOBdfH_l2{piR5e5(2e0_lz#*x z%PTPd1*d%aRMK6<=*ng_v@0@Y#)}_zS?)Uq)y>L5q1%4JxwY1y@AFRDQ^KsN11K0E z&|r)Of|1xuq=*VHI{S|~slr6gZgYVB3!Y4_p@te`0d#Hce8+dRS#vGmO#P>=Id<;l zj@U0GlSfCQ^M1Ivo3f>eNRNx5{5mW>#SLT9<}FQJMc*BU3PYT-B|l92)FWcJM--eV z86M3|OdQ0qT^$~jSArzi(kiAlox}z2YL1e1Vb7JDY6|`oEv)Neg!Mugoq;?j;FA@M za{s2rJ38K5KHU+x8F6*(3*S1mtjL(zItEmJ-k6RG!$g`5KDHwY)2d*MDQ`CY_x15} zx)Pj~$8F_`Svg16xZa+gp3Fb<{{m&Srrw!8o?~dq%xt2?j^W%0xailHZqmu)V;4nj zDOryODor!D80L3wb0(Gn8#s^%d!&04`Aqix>{h>1zj4Mplh<%SGw(O9oSIt(wxdg6 zTTaRJk*YD|cP`-aW{qpKB>c+u`LT(7iHt2DRImj3IN0(&kVw&{d_htY{tUmK`{;6< zyxdu5FbA(&^324_GvyC{@QiSY>3Pfw1bw=a~W{o!#NL2Gm>3YYq9;GroG?GJ!h|$@%IrMA$)dUiJ6a-xLu) zJ3H9Vv_fvn-9uEIZ}3BohKBT^_f9Xdr)^eHJfQ&V*V0_sBX2ao#mfE1ao+|{RPmoVVRMUQ4nPoC_B4pr6x zx$_}iAg+3nWQFG($GvW&1)1dBN$SI392#3BinW3tIaV&#u0Unre>R2=dU{mQO)mrw zaknXG_f%cJg^0k9)K3YmQ_nW-S`Om-9z9Z>+6)x_yBO{@dw3e$!9(SW`KO7mtXzD3 z`A(0=a$Qc^V{g~;d_7Y){x2SnXY9(ul@u3GZ_%1rzLF?>uJ4ylSYKa%i7%eoWx~4I zotMbWy`K#je*PN19kF_)mO2+i$`(F(B^02eGuH4cuuDUM5KNXS^>hm{P|lSwJ|<1a z*6Phl8>fUid{yrxz9IFKqQRj04l#3bY|4>C<5&NX`0s2-G1krnK!%H0o}mv&D^EF} z9c@m{xxFS_hndOG+|_ypg$nn7T6m=VeXH2fq#x4ey`};LuA@#vt_JAX{3%F=^k{?g zVmnUi5!@RlFZ&+wNd=2OmD>&tW`G|}to4@n2#6#?(>MKe2G;ahRUI9Ra5KdXYNe;qRN2so0GT?t7HMn_Zpr`{cW;+(c`v0>p)3(r(AI?1qFpByzpCz{aofF z-A^-*9zB|2IFzy4H;MrRXmp}CZt=R?Mt}`z%X~7gDvHc;yfaeQ?|V%r7aZy*PGeg< zg_;cn_vd*u^T&KQjkEdO)un6KAdpmMOsPX^M@r9J{_X+PQ9XlGR8$QVh2u(&u?8&5 z-J@iYxH#1g%W#?dB;A1Hylvu~W8V~5JbH~BeT4>6=~V{9Ko-HXGpO9s({H@(lx?Xb zHhsKBYmI9=Ix$X3+NecnQeePOVoNsoOjqs_-%Cf=zxEa6G|6~gIkk@)KTQ@1Le7=h zD^q?=R#4K=;2_n_AdR3GVFyR`sSA(_o?~W!u=v$=5#jpk^2GT2KObR;G5qrTyCFMR zmBH)RuRVSRHd@vNjJKY$eLF7}*Xe!s-VPdrlfm7^U&YZ8HXTa{yYp4n!?oEWBq;SbzJXiqvQA(`J%wIh|g@ENiC~~c;pNi3NEodQ1Ddl zu=*tn-8}N=d*amxrYz@a>Uoi~{3o)~SqB&RK}rsEqbGYZY5z;^IU4-M>+V3^pJqB- za6;GYR&lZae;?|RdbVxSngF`LWAm^{h5BBSER zbl)Bn!BPJF;&EDXk7&G;IFS$gdJ(-dF-fUA&8%p}O?vtkSbo?aN;t>!V_VmDYHOM=dn70dOOpluatC=y21liXBkN^4e#Mn=2(wK*d<>$NXO18d zW`WRj6S0EG(};-mXwryzBEI~#WoD3}IEUV);L29`hWLo=_zYFl4U1x#u&+cmoMVYsTc{;R zV7w3MfBr5y=@B~#dUJA6(-fbO>|^>>IzI^~XQ;`4tPM1K5;GAu6YU zF^~ejduy$TALY=<#5pgoVm9v6@~vLAsmoGoo}k;je0IO)Q$2a&J}^Lz9;Mx&K3|ei z*aq~QQ=X0zZP&cKjYz6xM)J&7ZpbShpC@ijfgPPbXWK{Z3mwNZwBrK;r|%eIzq#GL z_e{1BQM%GNsqx)q`rU18kP101X>sHB+54R&w9Lrm)r8#DU)9)#(`5oT=%vQXr{ZB} zt8sw+4_qzqD{Zrvn{3ysY;YjZn>?_#v$NwFez^ef-mR@I;Do|}+_g8D6i7C^NEE_` zy9k$EY&YYYJ(s!5+5+};xNkodHuboaN7Stz)O2m`5XfW$kG3H1_v+{W@zWgr-G9g4 z-1S9%RnzULQtoQgPV{_s;VWRNv4m*?#$4Pb_FYNt-hqxjK<3P%n zm*rj8x`eZB=hJ`FlGkm7Gk85$d;|w1LZF<0FOfT6zRpdB(5aLklmPPC6XxmUWXvlO zc6Rh9@NYK40UP0>jxZ~Cy(VXAwy+;Yh?B#wT3t^uzBOzMUH=v$kM1eK50%)NoM6MRu_wGwM;;F>EiC~_ti!jFgz(FT z6PD#@p#^!O6`1=`!^VTOjg1ciFJ(5JqS_6p68qQ_Y1R;w&`Psrs>R*uwY5j)-$JeK z5(_1FI|)jWzdY+$?()WB2@exvmH&(tr!HOo*%2QFfrxgvG0S^|^+yD}YWR_=H!A_4 z@FP~&8&*p#zSz@n!YTd1Sn<>F(}3{PeiqN4(%CNC2=y%^%kjYazJ2f2q#0+ z3mgY&Rq3zjqAbVC8$voWoO+Gc{B>Wyp*l9 z1a$urJodgtt<^LiHTnlaT7Ru8pP4IDW}5 zEDoiz(^&-F54AA$<;~@mWs5P{aQ6NlAYvB@^IGZNi;YzwJ*{ANdHQsLh4~*%biCV` zjobF2C;TcrimaDD99w%YUCn9gPycFnEwSm;x*;zn2uYgtk`{yzx4$J{dQ&Z+-6-GwJ`cly{_Mq9}9Q`t>_0Ao<)_t-M&1)(>CTdbD0Ac&7|9DQ)`n$P#(}++&1yvBlrL zi_Mj#&hsdJcl0s=?>sbZT6xsnEe}`<8m3(a?S-|fXk!bO}q^BA511w3NC58hA(6nKTsN*7z>WkCcwFeQP!RLCE z5@m0kn8>e&%H{t4b9<3N(MyvrCIhX9)`6wy4Y3A%D3foar;Y?Y}bP3-vNtSoY- z%P$S|wFTyNcx4T#Cr>txgNfwX-U;`A`0(Lqvr6K2m*3`OXV~TMgU|LR^Y4y>H~5#S z?iK9CCO(TMfaFWAuw9=yO3$CuhcbO{PfXX3j2P)mc@H*MR_7WS9)Z{nlbPw9o*;pg z-@Dn{M2hlvXqa51F!GkqeSH261INB(u3F42cPZ{Mn+nSQh`u9WG|kQ_M$_Bmj?WO< zYdE%rhnxV%M*#g|R4$0?RtpKonFlb5&df*+c>QHdLETcb=r^7v`kxC*!~Imq(yDNf zcoHW0sQBV%{;_Z8(p>Z?Z`jO#(+t1rT3l2W(0q6+!LCfyaSq1kE>ch;;VNf= z%JQ)50d$I62{D~5*`p2?v&Dsl3ti#i0Rg99zbbQQDttXWJOmPn7HzL(Pk!32dO>On z6V|Z`0k|`X<9k0p;42~=e62tQ6g+f)XJ0XZ3`IX!bxRgKUKRm-5z@sP<{ObjA}}Yj ze_y(PJ{l1EEV0~h9_aW@O#yAjvRBH@--RK&`}l#l%H+TGe(01z=SeYm-~4>w}#je#R;TBmnx zCF=vNI`6+WYJLk0V0J{*>$!INQo%(Ay)R}&!L;RDvvnnTd7qie=VR<2mP?u)E{Uj+ z*~Yxzr@k%7_52-FX)k|D=`p%$`uGluq{PWFE6kb%yhdIsS-26_!I=33m7GkQJyf2O z>1#m-O4{thVaJ6~Qxj@hyxD48ejK-Kf!nBQX*tg}vXlxv`{-frbGE-~JCFj{LUprk zhkV1sUpwF)4L&Mi6vPJGd>1C-Wy2(it-M{FFxJ%tA_fp3Pa`LCa&qeW{yxbM#xmW> zV12I0OYZdE{gugbZEe>zlqwNXyn5Vi?*YtMG0U&{Uk3T{%f5U4 zy5q;vOU@d_}YMDqd1 z2{@)mO--GcHS0;$JEBjaDR=||Q6ByGe*sDriPaIGhtfqD2gx1|sf@j`Vb=0`#lATf zD8PsT*6W?mlB8J?qmP#$dZ?dIB2G$n{N1YFwcpnReH199thMp;@=6nV4IG_vg&dzD z>IUBPxZR?*2h-5p4ztm4)-6DCdTw8ZJs}1W6PeLc`!{EerC-M7U1Pg9?(>JtM~HdwAi=| zZpO?r>}Wz2Al3^_?x`||YG!6Yo=!}=(eI_Y_}vqVUIf#71NN2FuZs1Pc{a>c`Xb=_ zM{&^y85t2m-I3|l@Avy*eYLcWE-({93v%$bwDez6>A!*LdYvBxOIiwbzD~)OoQI`ry?zF!>C=2QE=LF*8(!bBPk0X$n%34`AcwDs`UgCfFa&To zfa83ra@U`;CihNVqn$XE-Q9P_3CGxpjQtN@--Kz{&jZ47%~Jd?jLg=k$;pJ-PPd(| z;ANuvR?Coha(Us_+twb@~5R*`W$m~CTKcH7eB5yP56t^prvi>g~2jTerAH08( zGgC@snn9&VO8EHTS*dbL0Rnq>;;?Hoff3~Z2R=5OeQW4L0(;xGSb2Hrjd~2muUPz(Yv-=$#uTD#eh2js&5} zd|VJ?rXo<`FF zNK-hX}5; zE|0PP{&U)1_Ua?k)n5I;7;0aOmG-i_Kh2lA$)N;rC3qQulE8#E4<<$&6o7lxvX~Ju zkPHA|@+MVnca>MsXYl;O=QFbf1QY-Y%IM~%rh>*tT>5PA;>FLTl!oDz(g9+K+Ol17 zW)fklAua^JaA716FxRfFJ#wU73p&~b#tgNa^Ub=Mg%9UwE ztgT(G?PZmc0H8a4Z{A=2rL5X|TIN{NUV4n-b(aAzWs zXlrYG`Q?{A9#4CFdreL4=;-L|?5ys-u(-Gw3WaRjHVk8FX~{GVT}qxPUDdpK>-h^q zVIhKor*lgo!ApFBT7M`ScFSV8wx%LwMGkz@JNVhSa{aCnpbY2kO8Ay4`V1zRB7{|| zO7ehm&MnJ9#84=-Fu#xo^wUoVwr<_r+t=eUk%;917iaUz*WR#aBnmetnU5(tFLD--+P-J5Et`~LkM z>((_%Npo}a(Ma^bfdh4QtE;N2&tDk${qH}B$K#tfZwUnaYuB#bzyHAf_us#D>(*ql z>h;%O&*gHvcI_%DDf#r%{-&n&0Av{Ei4&iM!{Mr`D!<=9K6<%f-MR-l=j!Tf9XmHR zJUl-+vvt#E)50fsrJZKok?%lgB%Zh{}<>lp@Hf;(70;9vj9@A5u zOs;82b?yAY!u)J!XICbZo0*>1x7K&;=vckF_Wb#Qj}9Ih9T|P$g@1YS$tNR`NLN?a zkAC!H+qQ`m=d7Wj;fW{yJQ|IiIn&qN+>%bGBauiX5~-}Ltgfz3Boc=X9on>cb2Jv) z*4i>TGd@3lW#r;`N89%F(#+o1CwQe}t_y8!fU;C`V{I(#=|6V#%=Gj^_PfAn0ag6b zk<8;;22=>~)KgDcmK6?#D=I2(2hemn-O+Jh9?+5Dk)QqSg_VE;fM%32Or=uSGa3$u z6N$u48ND#xv3+}bY38@Djq{2;quUy5qam~Z__4Ev4iDp;6Diwve);de)Kf%6tg1>5 z4GpH#>2>SY0kVa~`N_$N1HaoZmBSd0jg7wl{`=F@Q?s+vtLs)*RV7A8M;aQ|1cLzr zn4O&s1pJ)y*4DPZzP{exUZqG%wSN8j^74wYvCEB(Ym}02zx^BSeHV#D_V0ghXlM`s zq*8z|Hahms|NORT)20VHyROX47=~F^lk$f`zLGeAsHm!cptJpnA9roPccVXaw@=nr zsOTptLWn$|UawaJT3uarn}F8U*R2E;5a;IRg26x@&^)6`(S{8hu4hy`gWr_Vu4P8c zYa9IG@Kr`r4|MMM$)D}qes96I;h2<)F^&jRQ&$51;QZXefB)C7-g#&5Lk~SXHa2Ei zIY43@EN8*v1w|HsLuA|bqTwM&E+MlVx%k=8`Tu=CX+dNvga4S_%|X*r_+{YGsd(-g>Bn_h@45Lh?8wQ3NgpnrO&5d`_b%7 literal 25513 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 qa-}tj;HGu|#_sky*4tW-3aUiL(EooXpI^NI diff --git a/tests/media/Burning's Video-ambient-lighting.png b/tests/media/Burning's Video-ambient-lighting.png index a49b3071e27b5e8cc5f6564cc3ad3316ce541b2c..242d8d753a12ff7a002eb93b4f0d663ca7de4365 100644 GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^3xK$Sg9%9fI*@0EaktG3V`FN8V-!5!Z{C z9&k!8UU=w3v$lxCuFST3a~3~PHLw3W-SAlVy67Jd&b8XvRt3Dch;_t*U8$^RYyTDhrV`wroaI;yI{$ hPJHM*iIGL@9pnE6tRM6rm^Cs0fv2mV%Q~loCIG{%Ii~;s diff --git a/tests/media/Burning's Video-draw2DImage4cFilter.png b/tests/media/Burning's Video-draw2DImage4cFilter.png index 352640e1a4621432613f9eee74ac72fd75889a8f..b0629d89d4d2430d2377dc348769765b3cd07ea9 100644 GIT binary patch literal 23716 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

JyV^mi-hP`+=h3#bwUV5Cusd6w?uHE)& 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�M{m- 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 literal 27905 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 diff --git a/tests/media/Burning's Video-multiTexture.png b/tests/media/Burning's Video-multiTexture.png index 338f257eda01c31f705e223c98f71d9423330751..e02176b03467aa6fee5d1c4dbbbaf47ab1ae3759 100644 GIT binary patch literal 7646 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 P00000NkvXXu0mjfR^G@y diff --git a/tests/media/Burning's Video-orthoCam.png b/tests/media/Burning's Video-orthoCam.png index 41a96b8b9557a8baa1e18eba3e244df781fb5358..099f9b71fe206441303616e27da5f21fe7827f29 100644 GIT binary patch literal 4542 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 literal 4468 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 literal 37083 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 b2K@g3I}j7@Nvfd`00000NkvXXu0mjfnp(4U diff --git a/tests/media/Burning's Video-renderMipmap.png b/tests/media/Burning's Video-renderMipmap.png index d2d53210d6d44b2bf1298e851479223f2f22c588..74b8e7f1891a07f305b6048ca17594b38f0a1531 100644 GIT binary patch literal 814 zcmeAS@N?(olHy`uVBq!ia0vp^3xK$Sg9%9fI*@0- z``+Ha{7>0Oo96gsf0(v*rzc$eF(WtOV#K8Kgo`)q3^;Q1@*hkn{qo;w-u;8eldfHS zZknu^|BwIOo<`~A@0R7f`OEv}td!0A3+Gr{4}9*@jSM(u5x;1E$<|NW-&Kl=`Tne2 ze$D{MGUl<_v25u=E9csGnGX$q7VKWl6{x5+<>YazR-4B6ug>1kHa0g17T@1FziRuw zz$sc@wfk2HES+zvwyijtOR-I2sl<{65+Yxp_e-c~y0B`xXlA`%B{F+A<7wd^8|Qh> znppa)?%93$%G&J3Iw4}aKKO2&z-FrU?a4}!#~SxePH=QzAF_ExQv6NpS%F_wFZ`BD zp4$(!_GRv_X8V}y1(B%4=$uWs{} z(px<{XMw=ikI&-QuThnLeT9cP{G0yk1&f=fw*3Ec<3{WEmN|{ir)FRLJv~HE#k#8c z$)3qmznl{&)wX2b{*dc>m8Jeg-aXrQ|4caac)?roV0lB|n)<~z@;03d_^f^Iz-5(U z7PIS{4!k-2Dl78AuHT!&^yjB9N^Q(uxUPpec>5#C8M~AdH}9WX&F69AGtV)O#J+37tQSk-?nChdey#2^P$UB_+-sC}3+drnZpW*P<)= z$K`k3uAD9Nrv7c-|Hp@Hn)`RvF!pjA7v$8iN?Vxu9paObe$3o0xns$fy)6q9*w(GA z)lby;HM9Bs>LvX}-oe$oH`xAZtd424UcdXDxE-mBvr?^2f3dlpepfbK<`?H5BlXo%_bap3*F@^ry*_^~@A9%t<4oh7JMJ@0 zFOR=8ZHwww&%ZybR$rMiYf?-(BnmzG^I$vt)Z@cykTs-^!XpYC0L|GLG6V_$@Sg!=8e{qvz; zTEFq^XEn1nzugn9{y|H%bduHo36HPOzAc~pfY-8i-%91FldP_Ie-=Hygk7TMu7pIs zL!)f(Zi58}ly}_g75Jd`T9GgBcl&quT`+&C}}TOJ5!C-<9Do z{l(6OS7mn}WWDx3HNm3dLE+x`vPPL3yBOKGy^}F4(7d)c>|37n+g3-L=B)>461}LY b=QsP#{Opw{bzj*7Q!j(3tDnm{r-UW|6lGL$ diff --git a/tests/media/Burning's Video-stencilShadow.png b/tests/media/Burning's Video-stencilShadow.png index 77c53fd6cc153c96b40c9fda736f07b4fe3aa4bc..0186a74aa92ef08190f161c8c19467ee0dce8f5f 100644 GIT binary patch literal 3495 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

FJKA#|)=NpD(q`9ltSMvY*IY^`2 z+r$@~vA*Rz@vB(mxaIO$Ai3%SzrelYw8OnTIoB12lh_TC8XGXTSj|?V>Ib~DR)`6) zXSHxJoKBr}=X8adrzoZ}P3mK?&C9JjU0NcwOJaWv9??#x+9@McBcJ;!J@L}y7vu8; z0>*+a@Xk)E4ubQ=GHpwcOr9oS*>dXxQ{aFTtj7rUdoOjOiEQyk2E^&b<28jFR_e`W zKo3ullhxj>NVH=9u^pJ$IOSLQXreM5Y>2C zqRW6y4GnpZo#W!S;Urf+>8tO(@^weMcBMJc#-tR$;l0~l2E`J1QchO$(bAO<{27+x$oUsIAW zVeWn^{xu&OMM2j09;g69zU%tK&v@&D-A};5oyZ!;k(5u?3h7stG zFA33;$&^5R(+$oWfKNag52aqly$$Xow7>(b0o^c3(g z{hH$J$URve)YP8JG5T#VmjA|JHaQ38(*&ghDdDpLe1uCZn*$pD8miUJZ8N%Q>s8z@ z6-l=E;_qXprazW579=bP=&%k@pazGFnORiv`4$0nbHT>EvBnU6H7Y(Tb`Z#9og*Qx zC@Wa@&rCi$ zGtzY}$iOg{32ZD1wgWmC$m`S2%Zn@bCcF0X(bIbO=2`uPO@8-PR1j^AuX*h$A6jf$ z8GoIWgXDrRvgifkHAJx*TyaV-#tI&o-Yhx4%dv1-s7couEEnn@-wey8L+u&w6*b9N zNBbhX%@W{2+8rMVs9 zyC*fSN+A|9bexJA*BSta*+MBa3nQlL&GXg{N6V zo=xJH<-C(GX(J`(L@JKj98@C)I>qCux&ogRSc{6AWZRZ26L4Kqt6R1MF{{_`8D ziyZB*qYoN)!#mj93!X;kC=5nE-c0!FP574Nu$FJimZVQ=tGKe?BvV%Pr)2I7gi}dT zXyd}{Uywxx^i|565C3_g#<=`iRllIeC=Ae6#)fw2a0K6s z57lsB$$V7?!vHafaSpmE3oe)IQ-&El-!yI!Dj3@V*@BvM0j$>JQ|<^{1qCujA4kQ3 zH82QppDagew~)89>|E3@cd@D9hIUee*6yGqSsKZYk9cb&%qLWh2Lk{G8UpmY#m(0N znJraRvA{3}Dzv1ib@qFMony*t7d=pPrPI_vTg2LGdua#k?R1>;;79ZEgWKS{2OguX zN6m-1PO+^0^ScPvU|PT_{vE%#PcdK=2f_SKy)mG*vrM#$5%t);ADHrT?uhuXY)VBy zPMjkJAit+wRc6zWrFF7!dASLJHgQ7l6pPHEOaQ#_fDu4flgj%0Aau!~ik@UQtyZ&< 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 F`yT>vq3-|y literal 4337 zcmV004Lh0ssI2`oL~D000oUNklmL+{&2bt{K+)W^RGWG!%aUz^E`{lx~{hee;}!Km2MCIC^FNo z>pD%-G)=b$e-5GJ8r>fJ3FJ*XO_N^S9{kVKJkRU8(oMT_8~7ild7jmG&0m*gk(YJ# z`iAI#k`R+MpHg!^pHF$&Tg%)Y{Ev}&t&&<-Ugp$mHMTx|%rE*A(%!U>!enY$7K^xM zTD{mzlWrUT&E%cXjH&YizHVSU~8^}AJ!Lq!JWebyEUtd)If#t09?ahA! znIYD7UDwqd&r&M&S}n6Ii&-5h@L;_&O_Pp@AML|UA(>qTra($+)MZ(o&!<{if0~)e zIVT+*q48y#g5UIiAY4oqa5J@{M2Kxh4ej_45p+{>XiULx`cb0Ds9OaBGoR=4i3QB- z$hw?Jhe;NCy=)!-_U6lp{6}r+(xL!ZR_p97My7Wc{jyXF?r>9w>Njl=TH*mu-+Gyvh^sO z5ZhmCQ7p*{hf)^LL$b8~&ccW=gHely^Ok~xXT zRdFj*s7&=yEQXj$nx`ZQeHyX$m%J7_LVL`xfP&Ry3KGuc{$g+iNi=f%Eu_W-0M4DgM z_1nO+Td>BVL<1*WB=g2AAo?>bO{op4zWzyM3PkEy)-=`^%{TKY9_?qEc{V0eM9uH0vTRqGP$W6 ze%9n2nzqCKW@Fd$!vb0@&k9rMy^w1+L#aGI3&r4!$P4WzrGKI8BfJzsn@oSz4m3r| zp*;iu)A`|TU?G;*lCeWvw6s<$TG3!MkX~J;c>F1A92sV_6gcT`X zQr%$?rR59zSwOV4E1*LGT;wFHBRw)TQSfwu57@rvD3e!WMn7kAoP!>wtal#ItV)(E z`L(JHK0TpUr{BMSV~P~E8s>8LlTv>VN;r?Iy*W$J#Np)LVCJcSwN8~#1DKJ7I@G#h zR!omV0cxv<9NruLMcPKA+o#+RJ#jK`*Esdj*VotbT9;Y2+f#n0 z6MvGaaH+^I3QjM=o9l}t83ELH>!vtbVB2S&XAG8go=AC?wqm*!SPWL(;v?OkRYXLA zZQ3$BddFbNhpq3MF%7}l<2iQ52C^Y-owX^2d1+B>cr)ym#~T{czF%H-9(6q$@A^qZ zA<}N5z(&)5|NR%jFZF844+{CH?3?spj``OxNbg=6?N+umN2xN!pohRkE1Dtd+H7Qgt?ZC~NyWy>mb6SGRuZjCxk+s> zt!rYFN$kQ1IU|!fT8#6t+35Lv`hggVHw?5i)WZG_Vf_92Xy)(Xc&T#%3Ri{4XMe3H z=ncbUs&MfF+cSL)G0ZEc&{bU~#P+(1FXLsF>_kV#v4$flqc!rU{i{%ASw)Zhon$1- zjfsZNQMlt_8`M?y0ys7F{s@a=wc=F>Q}`2eV`H~$=a)X1nK5j?!5+=8HFWfQ?{k__ z7uNOa$dU{a48@Zd(t7e%uVD-?`ldQi1qs70e<#bH6=1b2i(1I{L0)I@tQOgubYu}u zdD`$Its#If+xRWz)M9ZMP zSRJ3}j9_N4uuJ#|m-0J(wm9t%8YuY)5;Doc6aGBLBr8*t-;2@|&L0%#j2BwP+)D>_ zh*VZfwr|d$!yRl8Z$1z?he8`N6Vw!=&)+n&DGbUMxBc

<9!xt18_RHyo*k0R@`jwVegVGNHYF ztm(Ku@ho2aX;N(k-YfJnh3P{L(bfU~iem`i_B0CwUVS038)r+i*X=QVI(nW_J!u(g z<8b*4Ss4W%BQ=Nc3RMbo83F87%2p_SP_(C(XZcnZm(v;Qn0py#JQXA_pPrJ}v&1=2 zX5BM>CZ(4v4O1`@qca*FKD>q1ini@0T8^+6!+Ch{$_690u1;y=#vWN>XqF2D2ex8^ zAe=P~O`a7qA^m;Ns_C7DsyloBL=QaMu(xd*l3^%aT;fW{V!VRLcP$^*9^&qW1>h{E z*f_9rgMPl0*)kj`p<1#y+6f04k*YCZ@1kGCj-<(iGqcqrgPx+BVs$hj7PAY#-+-ek z>;jEK*{0%t5Om0wq}Q(LexGv<%h*bG);Mb`O|r6tkn$S;C^USSmr=V}?lweAdNV4N z!N1&B_Y`YoPp_&H(olhQU3m@Y_>1p840!a!vb{~0D+#97Zn(M_DlS|}CB z_63gS8)rL#w(5EcGZjOKzm0sFw{`8IHvTUwK0-Ydz}1@Du$NfiGmpCVz* zDRo;D?G&c3I4DgRdo)BjQXipFU%7o7AIPzH+4zBnjj2^@l4hr%YBp6zM`L^tmj{I|lD^d|Z{xKr9Tpk~p{3UA7dKmwYVl0)tHE^AtMwPgqw* zuKbXE6+WzH@YrcMV?}W{94nqxi21%e<$V^IJLyRlcbc}zgfE)DWJnbw`2DrntQv_D zcC~QIED_C63uX0=n7J}#ZCD<`pij+#UexlB_EyPSDVo4FUFG~<=op?|@~|}%&G$+zDg|*5$?6?o$ojNi?1n|FXA~!-$s$e9OxJ!D$aij zZUrhd1t^>>gQ8uO<<-Yn)lI0zzCAd!E@84)Qzxa$h$cvxtO)g3n1q>u#CcoT&;h{A zO71fD$+gUyaMNi6(Y|8`a(bK(&?9e;BDmIRSC+j~;_YQC1ZdJQjy5fKp&wJD{$<_x zM2GB*F_z0v-6n=h9$Y0?t26)rcQP>5sw*C*zFS|lCn1TYOlc2%Npfh~P}j|rYKY;@ zc6W_{T93x3?@#@3J~Z|LKR%G+y+5Ob8TPLB2yCogs`ozBzeTQX^h474t=XN3gje%>v zG)ZWd4DTE$Q1c%?HS4Z>K4_aYbk(s9WSG5veum!Dqz)aP0`7{MMFEUJ9k}*4_iC_! z){|+lXIMNvL+^!-U1HV7u5+T0ZAbOA@#SUC-Vi@ezQ6s?zBDJ?H0#4hX9m+|p`%uc znIRKpZ-QOt)qZkJ!`vTMC8dYm+57PuIr zn`s=yDtv2~^vkkL)AUu6^m6ZJ3~pktS(ny)E^+8fa`i`cChOQ>^r=v$(C{6@kSs>j zy|oE__O(_S1)4JfmAY`1rO$6YeV?ktJcR~hM&Vmrb@pGB>|{gD5nU^#{`l&UxhHbp zaQ=P9NPFY4kt+GygXz8LjzE4I(^OD%USx&oEr(3DCM5U{UYkFLO`mk=Gk&~@!T1qh zyV)5&wRQV*m0>28aoYt6^rHHC^7uU5aoOvXd*^$mkOz)vy+v9^2MWdN=*#+C7ygR= zVMWO80LEY|;*J1ZOGBSK@M(@?bNcUp5RH1YPaR}pDVg@0d8x7;X3l-%Nkc&eH=4+v zB;Qb{BYPdXsT_2S_dkf=E6MHyegwb=Q!@!u@&S@>Uuhs23uV(gJYdpiO%y_3sQXE=C=9uAs~2M>Yz+GHUc z6ZB8fv`jI8eBqxkv-BLgIXgNj8(P}9k+$__bta4CD6EBPPQScwBCJ&uu4O*2$E*qb zd8~=6WTO;>QWgn62%b4g$9E6Ny~}JJ*Ic$QGz`lhBbs!PX8T#>85z7eJp~@@i#FFB zc2x;ot>g64P|a8J9n`uD2Po9l-s;0DML5WQT9wU-j*R<-)4`(HfvM+#oM6|v=)Kfj fPU&#CN}m4#ypH;b?_j;M00000NkvXXu0mjf&1qr~ diff --git a/tests/media/Burning's Video-terrainSceneNode-1.png b/tests/media/Burning's Video-terrainSceneNode-1.png index e7a899355edc3c0fe026763f65bd1dbbdf7dc746..d105e824700c9ffa05d9eb1c964a063358e2b934 100644 GIT binary patch literal 39271 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 literal 34251 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 H55xZ-O|dVi literal 8117 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 Oz*RGAM7@d2qyGVgtoq3S diff --git a/tests/media/Burning's Video-testTerrainMesh.png b/tests/media/Burning's Video-testTerrainMesh.png index 802c4ec21eabd7eb47c74f2200aecb76267334e6..98a7c0d23483c610e1c5f94362d9c4b6b0fceea8 100644 GIT binary patch literal 33283 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 literal 32006 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

  • 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 literal 27349 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�M{m- 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 literal 27905 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 diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 969e94a7..15f31461 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. -Compiled as RELEASE -Test suite pass at GMT Sun Oct 25 15:03:26 2020 +Compiled as DEBUG +Test suite pass at GMT Tue Dec 01 13:34:31 2020