summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@debian.org>2018-05-15 13:58:15 +0100
committerJames Cowgill <jcowgill@debian.org>2018-05-15 13:58:15 +0100
commitb175eed3ca950204c9b52fdcebc897f337b7bf19 (patch)
tree0f50d921750c957f11bda18abc83f9228d010902
parent31394fcd65a10f2d2c51c3d27afff5367bded901 (diff)
New upstream version 2.5.0+dfsg
-rw-r--r--.github/ISSUE_TEMPLATE.md54
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md51
-rw-r--r--CMakeLists.txt362
-rw-r--r--CONTRIBUTING16
-rw-r--r--CONTRIBUTING.md7
-rw-r--r--changelog.md654
-rw-r--r--changelog.txt615
-rw-r--r--cmake/Config.cmake36
-rw-r--r--cmake/Macros.cmake267
-rw-r--r--cmake/Modules/FindSFML.cmake365
-rw-r--r--cmake/Modules/FindUDev.cmake1
-rw-r--r--cmake/Modules/FindVorbis.cmake13
-rw-r--r--cmake/SFMLConfig.cmake.in148
-rw-r--r--cmake/SFMLConfigDependencies.cmake.in80
-rw-r--r--cmake/toolchains/android.toolchain.cmake64
-rw-r--r--cmake/toolchains/iOS.toolchain.cmake217
-rw-r--r--doc/CMakeLists.txt4
-rw-r--r--doc/doxyfile.in455
-rw-r--r--doc/doxygen.css9
-rw-r--r--doc/footer.html2
-rw-r--r--doc/header.html.in2
-rw-r--r--doc/mainpage.hpp2
-rw-r--r--examples/CMakeLists.txt54
-rw-r--r--examples/X11/CMakeLists.txt10
-rw-r--r--examples/android/.gitignore8
-rw-r--r--examples/android/app/app.iml123
-rw-r--r--examples/android/app/build.gradle39
-rw-r--r--examples/android/app/proguard-rules.pro21
-rw-r--r--examples/android/app/src/main/AndroidManifest.xml (renamed from examples/android/AndroidManifest.xml)8
-rw-r--r--examples/android/app/src/main/assets/image.png (renamed from examples/android/assets/image.png)bin8849 -> 8849 bytes
-rw-r--r--examples/android/app/src/main/assets/sansation.ttf (renamed from examples/android/assets/sansation.ttf)bin28912 -> 28912 bytes
-rw-r--r--examples/android/app/src/main/jni/Android.mk20
-rw-r--r--examples/android/app/src/main/jni/Application.mk8
-rw-r--r--examples/android/app/src/main/jni/main.cpp (renamed from examples/android/jni/main.cpp)62
-rw-r--r--examples/android/app/src/main/res/drawable-hdpi/sfml_logo.png (renamed from examples/android/res/drawable-hdpi/sfml_logo.png)bin4339 -> 4339 bytes
-rw-r--r--examples/android/app/src/main/res/drawable-ldpi/sfml_logo.png (renamed from examples/android/res/drawable-ldpi/sfml_logo.png)bin2246 -> 2246 bytes
-rw-r--r--examples/android/app/src/main/res/drawable-mdpi/sfml_logo.png (renamed from examples/android/res/drawable-mdpi/sfml_logo.png)bin2949 -> 2949 bytes
-rw-r--r--examples/android/app/src/main/res/drawable-xhdpi/sfml_logo.png (renamed from examples/android/res/drawable-xhdpi/sfml_logo.png)bin5717 -> 5717 bytes
-rw-r--r--examples/android/app/src/main/res/drawable-xxhdpi/sfml_logo.png (renamed from examples/android/res/drawable-xxhdpi/sfml_logo.png)bin8482 -> 8482 bytes
-rw-r--r--examples/android/app/src/main/res/values/strings.xml (renamed from examples/android/res/values/strings.xml)0
-rw-r--r--examples/android/build.gradle23
-rw-r--r--examples/android/gradle.properties17
-rw-r--r--examples/android/jni/Android.mk18
-rw-r--r--examples/android/jni/Application.mk5
-rw-r--r--examples/android/settings.gradle1
-rw-r--r--examples/cocoa/CMakeLists.txt84
-rw-r--r--examples/cocoa/CocoaAppDelegate.h2
-rw-r--r--examples/cocoa/CocoaAppDelegate.mm2
-rw-r--r--examples/cocoa/NSString+stdstring.h2
-rw-r--r--examples/cocoa/NSString+stdstring.mm4
-rw-r--r--examples/cocoa/main.m2
-rw-r--r--examples/cocoa/resources/Cocoa-Info.plist2
-rw-r--r--examples/cocoa/resources/Credits.rtf2
-rw-r--r--examples/ftp/CMakeLists.txt2
-rw-r--r--examples/iOS/CMakeLists.txt25
-rw-r--r--examples/iOS/main.cpp65
-rw-r--r--examples/iOS/resources/image.pngbin0 -> 8849 bytes
-rw-r--r--examples/iOS/resources/sansation.ttfbin0 -> 28912 bytes
-rw-r--r--examples/island/CMakeLists.txt11
-rw-r--r--examples/island/Island.cpp590
-rw-r--r--examples/island/resources/sansation.ttfbin0 -> 28912 bytes
-rw-r--r--examples/island/resources/terrain.frag11
-rw-r--r--examples/island/resources/terrain.vert8
-rw-r--r--examples/island/stb_perlin.h316
-rw-r--r--examples/joystick/CMakeLists.txt11
-rw-r--r--examples/joystick/Joystick.cpp238
-rw-r--r--examples/joystick/resources/sansation.ttfbin0 -> 28912 bytes
-rw-r--r--examples/opengl/CMakeLists.txt8
-rw-r--r--examples/opengl/OpenGL.cpp22
-rw-r--r--examples/pong/CMakeLists.txt3
-rw-r--r--examples/shader/CMakeLists.txt3
-rw-r--r--examples/sockets/CMakeLists.txt2
-rw-r--r--examples/sound/CMakeLists.txt3
-rw-r--r--examples/sound_capture/CMakeLists.txt2
-rw-r--r--examples/voip/CMakeLists.txt2
-rw-r--r--examples/win32/CMakeLists.txt3
-rw-r--r--examples/window/CMakeLists.txt7
-rw-r--r--extlibs/Android.mk6
-rw-r--r--extlibs/headers/stb_image/stb_image.h2389
-rw-r--r--extlibs/headers/stb_image/stb_image_write.h1082
-rw-r--r--include/SFML/Audio.hpp2
-rw-r--r--include/SFML/Audio/AlResource.hpp2
-rw-r--r--include/SFML/Audio/Export.hpp2
-rw-r--r--include/SFML/Audio/InputSoundFile.hpp37
-rw-r--r--include/SFML/Audio/Listener.hpp2
-rw-r--r--include/SFML/Audio/Music.hpp112
-rw-r--r--include/SFML/Audio/OutputSoundFile.hpp2
-rw-r--r--include/SFML/Audio/Sound.hpp2
-rw-r--r--include/SFML/Audio/SoundBuffer.hpp2
-rw-r--r--include/SFML/Audio/SoundBufferRecorder.hpp2
-rw-r--r--include/SFML/Audio/SoundFileFactory.hpp2
-rw-r--r--include/SFML/Audio/SoundFileFactory.inl2
-rw-r--r--include/SFML/Audio/SoundFileReader.hpp7
-rw-r--r--include/SFML/Audio/SoundFileWriter.hpp2
-rw-r--r--include/SFML/Audio/SoundRecorder.hpp2
-rw-r--r--include/SFML/Audio/SoundSource.hpp47
-rw-r--r--include/SFML/Audio/SoundStream.hpp47
-rw-r--r--include/SFML/Config.hpp11
-rw-r--r--include/SFML/GpuPreference.hpp74
-rw-r--r--include/SFML/Graphics.hpp3
-rw-r--r--include/SFML/Graphics/BlendMode.hpp2
-rw-r--r--include/SFML/Graphics/CircleShape.hpp2
-rw-r--r--include/SFML/Graphics/Color.hpp2
-rw-r--r--include/SFML/Graphics/ConvexShape.hpp2
-rw-r--r--include/SFML/Graphics/Drawable.hpp2
-rw-r--r--include/SFML/Graphics/Export.hpp2
-rw-r--r--include/SFML/Graphics/Font.hpp4
-rw-r--r--include/SFML/Graphics/Glsl.hpp2
-rw-r--r--include/SFML/Graphics/Glsl.inl2
-rw-r--r--include/SFML/Graphics/Glyph.hpp2
-rw-r--r--include/SFML/Graphics/Image.hpp5
-rw-r--r--include/SFML/Graphics/PrimitiveType.hpp2
-rw-r--r--include/SFML/Graphics/Rect.hpp2
-rw-r--r--include/SFML/Graphics/Rect.inl2
-rw-r--r--include/SFML/Graphics/RectangleShape.hpp2
-rw-r--r--include/SFML/Graphics/RenderStates.hpp2
-rw-r--r--include/SFML/Graphics/RenderTarget.hpp75
-rw-r--r--include/SFML/Graphics/RenderTexture.hpp48
-rw-r--r--include/SFML/Graphics/RenderWindow.hpp32
-rw-r--r--include/SFML/Graphics/Shader.hpp4
-rw-r--r--include/SFML/Graphics/Shape.hpp2
-rw-r--r--include/SFML/Graphics/Sprite.hpp2
-rw-r--r--include/SFML/Graphics/Text.hpp87
-rw-r--r--include/SFML/Graphics/Texture.hpp53
-rw-r--r--include/SFML/Graphics/Transform.hpp31
-rw-r--r--include/SFML/Graphics/Transformable.hpp2
-rw-r--r--include/SFML/Graphics/Vertex.hpp2
-rw-r--r--include/SFML/Graphics/VertexArray.hpp2
-rw-r--r--include/SFML/Graphics/VertexBuffer.hpp408
-rw-r--r--include/SFML/Graphics/View.hpp2
-rw-r--r--include/SFML/Main.hpp2
-rw-r--r--include/SFML/Network.hpp2
-rw-r--r--include/SFML/Network/Export.hpp2
-rw-r--r--include/SFML/Network/Ftp.hpp8
-rw-r--r--include/SFML/Network/Http.hpp2
-rw-r--r--include/SFML/Network/IpAddress.hpp2
-rw-r--r--include/SFML/Network/Packet.hpp126
-rw-r--r--include/SFML/Network/Socket.hpp2
-rw-r--r--include/SFML/Network/SocketHandle.hpp2
-rw-r--r--include/SFML/Network/SocketSelector.hpp2
-rw-r--r--include/SFML/Network/TcpListener.hpp16
-rw-r--r--include/SFML/Network/TcpSocket.hpp5
-rw-r--r--include/SFML/Network/UdpSocket.hpp7
-rw-r--r--include/SFML/OpenGL.hpp5
-rw-r--r--include/SFML/System.hpp2
-rw-r--r--include/SFML/System/Clock.hpp2
-rw-r--r--include/SFML/System/Err.hpp2
-rw-r--r--include/SFML/System/Export.hpp2
-rw-r--r--include/SFML/System/FileInputStream.hpp2
-rw-r--r--include/SFML/System/InputStream.hpp2
-rw-r--r--include/SFML/System/Lock.hpp2
-rw-r--r--include/SFML/System/MemoryInputStream.hpp2
-rw-r--r--include/SFML/System/Mutex.hpp2
-rw-r--r--include/SFML/System/NativeActivity.hpp2
-rw-r--r--include/SFML/System/NonCopyable.hpp12
-rw-r--r--include/SFML/System/Sleep.hpp2
-rw-r--r--include/SFML/System/String.hpp2
-rw-r--r--include/SFML/System/String.inl2
-rw-r--r--include/SFML/System/Thread.hpp2
-rw-r--r--include/SFML/System/Thread.inl2
-rw-r--r--include/SFML/System/ThreadLocal.hpp2
-rw-r--r--include/SFML/System/ThreadLocalPtr.hpp2
-rw-r--r--include/SFML/System/ThreadLocalPtr.inl2
-rw-r--r--include/SFML/System/Time.hpp2
-rw-r--r--include/SFML/System/Utf.hpp2
-rw-r--r--include/SFML/System/Utf.inl10
-rw-r--r--include/SFML/System/Vector2.hpp2
-rw-r--r--include/SFML/System/Vector2.inl2
-rw-r--r--include/SFML/System/Vector3.hpp2
-rw-r--r--include/SFML/System/Vector3.inl2
-rw-r--r--include/SFML/Window.hpp4
-rw-r--r--include/SFML/Window/Clipboard.hpp108
-rw-r--r--include/SFML/Window/Context.hpp17
-rw-r--r--include/SFML/Window/ContextSettings.hpp3
-rw-r--r--include/SFML/Window/Cursor.hpp219
-rw-r--r--include/SFML/Window/Event.hpp4
-rw-r--r--include/SFML/Window/Export.hpp2
-rw-r--r--include/SFML/Window/GlResource.hpp18
-rw-r--r--include/SFML/Window/Joystick.hpp2
-rw-r--r--include/SFML/Window/Keyboard.hpp24
-rw-r--r--include/SFML/Window/Mouse.hpp2
-rw-r--r--include/SFML/Window/Sensor.hpp2
-rw-r--r--include/SFML/Window/Touch.hpp2
-rw-r--r--include/SFML/Window/VideoMode.hpp2
-rw-r--r--include/SFML/Window/Window.hpp36
-rw-r--r--include/SFML/Window/WindowHandle.hpp6
-rw-r--r--include/SFML/Window/WindowStyle.hpp2
-rw-r--r--license.md20
-rw-r--r--license.txt37
-rw-r--r--readme.md39
-rw-r--r--readme.txt44
-rw-r--r--src/SFML/Android.mk2
-rw-r--r--src/SFML/Audio/ALCheck.cpp2
-rw-r--r--src/SFML/Audio/ALCheck.hpp11
-rw-r--r--src/SFML/Audio/AlResource.cpp2
-rw-r--r--src/SFML/Audio/AudioDevice.cpp2
-rw-r--r--src/SFML/Audio/AudioDevice.hpp2
-rw-r--r--src/SFML/Audio/CMakeLists.txt48
-rw-r--r--src/SFML/Audio/InputSoundFile.cpp40
-rw-r--r--src/SFML/Audio/Listener.cpp2
-rw-r--r--src/SFML/Audio/Music.cpp145
-rw-r--r--src/SFML/Audio/OutputSoundFile.cpp2
-rw-r--r--src/SFML/Audio/Sound.cpp2
-rw-r--r--src/SFML/Audio/SoundBuffer.cpp2
-rw-r--r--src/SFML/Audio/SoundBufferRecorder.cpp2
-rw-r--r--src/SFML/Audio/SoundFileFactory.cpp2
-rw-r--r--src/SFML/Audio/SoundFileReaderFlac.cpp41
-rw-r--r--src/SFML/Audio/SoundFileReaderFlac.hpp12
-rw-r--r--src/SFML/Audio/SoundFileReaderOgg.cpp2
-rw-r--r--src/SFML/Audio/SoundFileReaderOgg.hpp7
-rw-r--r--src/SFML/Audio/SoundFileReaderWav.cpp59
-rw-r--r--src/SFML/Audio/SoundFileReaderWav.hpp7
-rw-r--r--src/SFML/Audio/SoundFileWriterFlac.cpp2
-rw-r--r--src/SFML/Audio/SoundFileWriterFlac.hpp2
-rw-r--r--src/SFML/Audio/SoundFileWriterOgg.cpp2
-rw-r--r--src/SFML/Audio/SoundFileWriterOgg.hpp2
-rw-r--r--src/SFML/Audio/SoundFileWriterWav.cpp16
-rw-r--r--src/SFML/Audio/SoundFileWriterWav.hpp4
-rw-r--r--src/SFML/Audio/SoundRecorder.cpp4
-rw-r--r--src/SFML/Audio/SoundSource.cpp2
-rw-r--r--src/SFML/Audio/SoundStream.cpp88
-rw-r--r--src/SFML/CMakeLists.txt33
-rw-r--r--src/SFML/Graphics/BlendMode.cpp2
-rw-r--r--src/SFML/Graphics/CMakeLists.txt69
-rw-r--r--src/SFML/Graphics/CircleShape.cpp2
-rw-r--r--src/SFML/Graphics/Color.cpp2
-rw-r--r--src/SFML/Graphics/ConvexShape.cpp2
-rw-r--r--src/SFML/Graphics/Font.cpp90
-rw-r--r--src/SFML/Graphics/GLCheck.cpp2
-rw-r--r--src/SFML/Graphics/GLCheck.hpp2
-rw-r--r--src/SFML/Graphics/GLExtensions.cpp2
-rw-r--r--src/SFML/Graphics/GLExtensions.hpp67
-rw-r--r--src/SFML/Graphics/GLExtensions.txt5
-rw-r--r--src/SFML/Graphics/GLLoader.cpp123
-rw-r--r--src/SFML/Graphics/GLLoader.hpp101
-rw-r--r--src/SFML/Graphics/Glsl.cpp2
-rw-r--r--src/SFML/Graphics/Image.cpp18
-rw-r--r--src/SFML/Graphics/ImageLoader.cpp63
-rw-r--r--src/SFML/Graphics/ImageLoader.hpp15
-rw-r--r--src/SFML/Graphics/RectangleShape.cpp2
-rw-r--r--src/SFML/Graphics/RenderStates.cpp2
-rw-r--r--src/SFML/Graphics/RenderTarget.cpp343
-rw-r--r--src/SFML/Graphics/RenderTexture.cpp42
-rw-r--r--src/SFML/Graphics/RenderTextureImpl.cpp2
-rw-r--r--src/SFML/Graphics/RenderTextureImpl.hpp15
-rw-r--r--src/SFML/Graphics/RenderTextureImplDefault.cpp16
-rw-r--r--src/SFML/Graphics/RenderTextureImplDefault.hpp20
-rw-r--r--src/SFML/Graphics/RenderTextureImplFBO.cpp508
-rw-r--r--src/SFML/Graphics/RenderTextureImplFBO.hpp48
-rw-r--r--src/SFML/Graphics/RenderWindow.cpp27
-rw-r--r--src/SFML/Graphics/Shader.cpp14
-rw-r--r--src/SFML/Graphics/Shape.cpp10
-rw-r--r--src/SFML/Graphics/Sprite.cpp2
-rw-r--r--src/SFML/Graphics/Text.cpp189
-rw-r--r--src/SFML/Graphics/Texture.cpp154
-rw-r--r--src/SFML/Graphics/TextureSaver.cpp2
-rw-r--r--src/SFML/Graphics/TextureSaver.hpp2
-rw-r--r--src/SFML/Graphics/Transform.cpp21
-rw-r--r--src/SFML/Graphics/Transformable.cpp2
-rw-r--r--src/SFML/Graphics/Vertex.cpp2
-rw-r--r--src/SFML/Graphics/VertexArray.cpp2
-rw-r--r--src/SFML/Graphics/VertexBuffer.cpp363
-rw-r--r--src/SFML/Graphics/View.cpp2
-rw-r--r--src/SFML/Main/CMakeLists.txt22
-rw-r--r--src/SFML/Main/MainAndroid.cpp5
-rw-r--r--src/SFML/Main/MainWin32.cpp10
-rw-r--r--src/SFML/Main/MainiOS.mm2
-rw-r--r--src/SFML/Main/SFMLActivity.cpp2
-rw-r--r--src/SFML/Network/CMakeLists.txt16
-rw-r--r--src/SFML/Network/Ftp.cpp10
-rw-r--r--src/SFML/Network/Http.cpp2
-rw-r--r--src/SFML/Network/IpAddress.cpp2
-rw-r--r--src/SFML/Network/Packet.cpp2
-rw-r--r--src/SFML/Network/Socket.cpp2
-rw-r--r--src/SFML/Network/SocketImpl.hpp2
-rw-r--r--src/SFML/Network/SocketSelector.cpp2
-rw-r--r--src/SFML/Network/TcpListener.cpp7
-rw-r--r--src/SFML/Network/TcpSocket.cpp5
-rw-r--r--src/SFML/Network/UdpSocket.cpp5
-rw-r--r--src/SFML/Network/Unix/SocketImpl.cpp2
-rw-r--r--src/SFML/Network/Unix/SocketImpl.hpp2
-rw-r--r--src/SFML/Network/Win32/SocketImpl.cpp2
-rw-r--r--src/SFML/Network/Win32/SocketImpl.hpp2
-rw-r--r--src/SFML/System/Android/Activity.cpp4
-rw-r--r--src/SFML/System/Android/NativeActivity.cpp2
-rw-r--r--src/SFML/System/CMakeLists.txt25
-rw-r--r--src/SFML/System/Clock.cpp2
-rw-r--r--src/SFML/System/Err.cpp2
-rw-r--r--src/SFML/System/FileInputStream.cpp4
-rw-r--r--src/SFML/System/Lock.cpp2
-rw-r--r--src/SFML/System/MemoryInputStream.cpp2
-rw-r--r--src/SFML/System/Mutex.cpp2
-rw-r--r--src/SFML/System/Sleep.cpp2
-rw-r--r--src/SFML/System/String.cpp2
-rw-r--r--src/SFML/System/Thread.cpp2
-rw-r--r--src/SFML/System/ThreadLocal.cpp2
-rw-r--r--src/SFML/System/Time.cpp2
-rw-r--r--src/SFML/System/Unix/ClockImpl.cpp2
-rw-r--r--src/SFML/System/Unix/ClockImpl.hpp2
-rw-r--r--src/SFML/System/Unix/MutexImpl.cpp2
-rw-r--r--src/SFML/System/Unix/MutexImpl.hpp2
-rw-r--r--src/SFML/System/Unix/SleepImpl.cpp2
-rw-r--r--src/SFML/System/Unix/SleepImpl.hpp2
-rw-r--r--src/SFML/System/Unix/ThreadImpl.cpp4
-rw-r--r--src/SFML/System/Unix/ThreadImpl.hpp2
-rw-r--r--src/SFML/System/Unix/ThreadLocalImpl.cpp2
-rw-r--r--src/SFML/System/Unix/ThreadLocalImpl.hpp2
-rw-r--r--src/SFML/System/Win32/ClockImpl.cpp6
-rw-r--r--src/SFML/System/Win32/ClockImpl.hpp2
-rw-r--r--src/SFML/System/Win32/MutexImpl.cpp2
-rw-r--r--src/SFML/System/Win32/MutexImpl.hpp2
-rw-r--r--src/SFML/System/Win32/SleepImpl.cpp2
-rw-r--r--src/SFML/System/Win32/SleepImpl.hpp2
-rw-r--r--src/SFML/System/Win32/ThreadImpl.cpp2
-rw-r--r--src/SFML/System/Win32/ThreadImpl.hpp2
-rw-r--r--src/SFML/System/Win32/ThreadLocalImpl.cpp2
-rw-r--r--src/SFML/System/Win32/ThreadLocalImpl.hpp2
-rw-r--r--src/SFML/Window/Android/ClipboardImpl.cpp52
-rw-r--r--src/SFML/Window/Android/ClipboardImpl.hpp76
-rw-r--r--src/SFML/Window/Android/CursorImpl.cpp68
-rw-r--r--src/SFML/Window/Android/CursorImpl.hpp88
-rw-r--r--src/SFML/Window/Android/SensorImpl.cpp2
-rw-r--r--src/SFML/Window/Android/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/Android/WindowImplAndroid.cpp18
-rw-r--r--src/SFML/Window/Android/WindowImplAndroid.hpp8
-rw-r--r--src/SFML/Window/CMakeLists.txt122
-rw-r--r--src/SFML/Window/Clipboard.cpp48
-rw-r--r--src/SFML/Window/ClipboardImpl.hpp45
-rw-r--r--src/SFML/Window/Context.cpp9
-rw-r--r--src/SFML/Window/Cursor.cpp73
-rw-r--r--src/SFML/Window/CursorImpl.hpp56
-rw-r--r--src/SFML/Window/EglContext.cpp11
-rw-r--r--src/SFML/Window/FreeBSD/JoystickImpl.cpp2
-rw-r--r--src/SFML/Window/FreeBSD/JoystickImpl.hpp2
-rw-r--r--src/SFML/Window/GlContext.cpp102
-rw-r--r--src/SFML/Window/GlContext.hpp38
-rw-r--r--src/SFML/Window/GlResource.cpp12
-rw-r--r--src/SFML/Window/InputImpl.hpp4
-rw-r--r--src/SFML/Window/Joystick.cpp2
-rw-r--r--src/SFML/Window/JoystickImpl.hpp6
-rw-r--r--src/SFML/Window/JoystickManager.cpp2
-rw-r--r--src/SFML/Window/JoystickManager.hpp2
-rw-r--r--src/SFML/Window/Keyboard.cpp2
-rw-r--r--src/SFML/Window/Mouse.cpp2
-rw-r--r--src/SFML/Window/OSX/AutoreleasePoolWrapper.h2
-rw-r--r--src/SFML/Window/OSX/AutoreleasePoolWrapper.mm2
-rw-r--r--src/SFML/Window/OSX/ClipboardImpl.hpp78
-rw-r--r--src/SFML/Window/OSX/ClipboardImpl.mm68
-rw-r--r--src/SFML/Window/OSX/CursorImpl.hpp109
-rw-r--r--src/SFML/Window/OSX/CursorImpl.mm97
-rw-r--r--src/SFML/Window/OSX/HIDInputManager.hpp2
-rw-r--r--src/SFML/Window/OSX/HIDInputManager.mm24
-rw-r--r--src/SFML/Window/OSX/HIDJoystickManager.cpp2
-rw-r--r--src/SFML/Window/OSX/HIDJoystickManager.hpp2
-rw-r--r--src/SFML/Window/OSX/InputImpl.hpp2
-rw-r--r--src/SFML/Window/OSX/InputImpl.mm2
-rw-r--r--src/SFML/Window/OSX/JoystickImpl.cpp175
-rw-r--r--src/SFML/Window/OSX/JoystickImpl.hpp7
-rw-r--r--src/SFML/Window/OSX/NSImage+raw.h2
-rw-r--r--src/SFML/Window/OSX/NSImage+raw.mm2
-rw-r--r--src/SFML/Window/OSX/SFApplication.h2
-rw-r--r--src/SFML/Window/OSX/SFApplication.m2
-rw-r--r--src/SFML/Window/OSX/SFApplicationDelegate.h2
-rw-r--r--src/SFML/Window/OSX/SFApplicationDelegate.m2
-rw-r--r--src/SFML/Window/OSX/SFContext.hpp2
-rw-r--r--src/SFML/Window/OSX/SFContext.mm5
-rw-r--r--src/SFML/Window/OSX/SFKeyboardModifiersHelper.h2
-rw-r--r--src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm2
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+keyboard.mm2
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h2
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+mouse.mm21
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h2
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView.h9
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView.mm3
-rw-r--r--src/SFML/Window/OSX/SFSilentResponder.h2
-rw-r--r--src/SFML/Window/OSX/SFSilentResponder.m2
-rw-r--r--src/SFML/Window/OSX/SFViewController.h2
-rw-r--r--src/SFML/Window/OSX/SFViewController.mm11
-rw-r--r--src/SFML/Window/OSX/SFWindow.h4
-rw-r--r--src/SFML/Window/OSX/SFWindow.m4
-rw-r--r--src/SFML/Window/OSX/SFWindowController.h2
-rw-r--r--src/SFML/Window/OSX/SFWindowController.mm13
-rw-r--r--src/SFML/Window/OSX/Scaling.h2
-rw-r--r--src/SFML/Window/OSX/SensorImpl.cpp2
-rw-r--r--src/SFML/Window/OSX/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/OSX/VideoModeImpl.cpp2
-rw-r--r--src/SFML/Window/OSX/WindowImplCocoa.hpp10
-rw-r--r--src/SFML/Window/OSX/WindowImplCocoa.mm9
-rw-r--r--src/SFML/Window/OSX/WindowImplDelegateProtocol.h8
-rw-r--r--src/SFML/Window/OSX/cg_sf_conversion.hpp2
-rw-r--r--src/SFML/Window/OSX/cg_sf_conversion.mm2
-rw-r--r--src/SFML/Window/OSX/cpp_objc_conversion.h2
-rw-r--r--src/SFML/Window/OSX/cpp_objc_conversion.mm2
-rw-r--r--src/SFML/Window/OpenBSD/JoystickImpl.cpp97
-rw-r--r--src/SFML/Window/OpenBSD/JoystickImpl.hpp117
-rw-r--r--src/SFML/Window/Sensor.cpp2
-rw-r--r--src/SFML/Window/SensorImpl.hpp4
-rw-r--r--src/SFML/Window/SensorManager.cpp2
-rw-r--r--src/SFML/Window/SensorManager.hpp2
-rw-r--r--src/SFML/Window/Touch.cpp2
-rw-r--r--src/SFML/Window/Unix/ClipboardImpl.cpp261
-rw-r--r--src/SFML/Window/Unix/ClipboardImpl.hpp77
-rw-r--r--src/SFML/Window/Unix/CursorImpl.cpp156
-rw-r--r--src/SFML/Window/Unix/CursorImpl.hpp103
-rw-r--r--src/SFML/Window/Unix/Display.cpp2
-rw-r--r--src/SFML/Window/Unix/Display.hpp2
-rw-r--r--src/SFML/Window/Unix/GlxContext.cpp7
-rw-r--r--src/SFML/Window/Unix/GlxContext.hpp2
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.cpp2
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.hpp2
-rw-r--r--src/SFML/Window/Unix/InputImpl.cpp12
-rw-r--r--src/SFML/Window/Unix/InputImpl.hpp2
-rw-r--r--src/SFML/Window/Unix/JoystickImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/JoystickImpl.hpp2
-rw-r--r--src/SFML/Window/Unix/SensorImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/Unix/VideoModeImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp236
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.hpp47
-rw-r--r--src/SFML/Window/VideoMode.cpp2
-rw-r--r--src/SFML/Window/VideoModeImpl.hpp2
-rw-r--r--src/SFML/Window/Win32/ClipboardImpl.cpp103
-rw-r--r--src/SFML/Window/Win32/ClipboardImpl.hpp76
-rwxr-xr-xsrc/SFML/Window/Win32/CursorImpl.cpp183
-rwxr-xr-xsrc/SFML/Window/Win32/CursorImpl.hpp103
-rw-r--r--src/SFML/Window/Win32/InputImpl.cpp12
-rw-r--r--src/SFML/Window/Win32/InputImpl.hpp2
-rw-r--r--src/SFML/Window/Win32/JoystickImpl.cpp672
-rw-r--r--src/SFML/Window/Win32/JoystickImpl.hpp114
-rw-r--r--src/SFML/Window/Win32/SensorImpl.cpp2
-rw-r--r--src/SFML/Window/Win32/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/Win32/VideoModeImpl.cpp4
-rw-r--r--src/SFML/Window/Win32/WglContext.cpp5
-rw-r--r--src/SFML/Window/Win32/WglContext.hpp2
-rw-r--r--src/SFML/Window/Win32/WglExtensions.cpp2
-rw-r--r--src/SFML/Window/Win32/WglExtensions.hpp2
-rw-r--r--src/SFML/Window/Win32/WglExtensions.txt2
-rwxr-xr-x[-rw-r--r--]src/SFML/Window/Win32/WindowImplWin32.cpp115
-rwxr-xr-x[-rw-r--r--]src/SFML/Window/Win32/WindowImplWin32.hpp13
-rw-r--r--src/SFML/Window/Window.cpp10
-rw-r--r--src/SFML/Window/WindowImpl.cpp15
-rw-r--r--src/SFML/Window/WindowImpl.hpp23
-rw-r--r--src/SFML/Window/iOS/ClipboardImpl.hpp78
-rw-r--r--src/SFML/Window/iOS/ClipboardImpl.mm72
-rw-r--r--src/SFML/Window/iOS/CursorImpl.cpp68
-rw-r--r--src/SFML/Window/iOS/CursorImpl.hpp88
-rw-r--r--src/SFML/Window/iOS/EaglContext.hpp2
-rw-r--r--src/SFML/Window/iOS/EaglContext.mm5
-rw-r--r--src/SFML/Window/iOS/InputImpl.hpp2
-rw-r--r--src/SFML/Window/iOS/InputImpl.mm2
-rw-r--r--src/SFML/Window/iOS/JoystickImpl.hpp2
-rw-r--r--src/SFML/Window/iOS/JoystickImpl.mm2
-rw-r--r--src/SFML/Window/iOS/ObjCType.hpp2
-rw-r--r--src/SFML/Window/iOS/SFAppDelegate.hpp2
-rw-r--r--src/SFML/Window/iOS/SFAppDelegate.mm2
-rw-r--r--src/SFML/Window/iOS/SFMain.hpp2
-rw-r--r--src/SFML/Window/iOS/SFMain.mm2
-rw-r--r--src/SFML/Window/iOS/SFView.hpp2
-rw-r--r--src/SFML/Window/iOS/SFView.mm2
-rw-r--r--src/SFML/Window/iOS/SFViewController.hpp2
-rw-r--r--src/SFML/Window/iOS/SFViewController.mm2
-rw-r--r--src/SFML/Window/iOS/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/iOS/SensorImpl.mm2
-rw-r--r--src/SFML/Window/iOS/VideoModeImpl.mm2
-rw-r--r--src/SFML/Window/iOS/WindowImplUIKit.hpp10
-rw-r--r--src/SFML/Window/iOS/WindowImplUIKit.mm9
-rwxr-xr-xtools/android/compile_libs.sh6
-rwxr-xr-xtools/android/download_sources.sh15
-rw-r--r--tools/pkg-config/sfml-audio.pc.in3
-rw-r--r--tools/pkg-config/sfml-graphics.pc.in3
-rw-r--r--tools/pkg-config/sfml-window.pc.in2
471 files changed, 14522 insertions, 3911 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..0fbd9e4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,54 @@
+Thanks for raising your issue here! 🙂
+
+Before you submit the issue however, we'd like you to consider the follow points.
+
+* We like to use the issue tracker for confirmed issues.
+* If you're stuck with SFML, please use [the forum](https://en.sfml-dev.org/forums/index.php#c3) to get help.
+
+----
+
+## Subject of the issue
+
+Describe your issue here.
+
+## Your environment
+
+* Your OS / distro / window manager used
+* Your version of SFML (2.5.0, git master, etc)
+* Your compiler and compiler version used
+* Special compiler flags used
+
+## Steps to reproduce
+
+Tell us how to reproduce this issue. Please provide a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve), you can use the follow template as a start:
+
+```cpp
+#include <SFML/Graphics.hpp>
+
+int main()
+{
+ sf::RenderWindow window(sf::VideoMode(1280, 720), "Minimal, complete and verifiable example");
+ window.setFramerateLimit(60);
+
+ while (window.isOpen())
+ {
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ if (event.type == sf::Event::Closed)
+ window.close();
+ }
+
+ window.clear();
+ window.display();
+ }
+}
+```
+
+## Expected behavior
+
+Tell us what should happen
+
+## Actual behavior
+
+Tell us what happens instead
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..92a926d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,51 @@
+Thanks a lot for making a contribution to SFML! 🙂
+
+Before you create the pull request, we ask you to check the follow boxes. (For small changes not everything needs to ticked, but the more the better!)
+
+* [ ] Has this change been discussed on [the forum](https://en.sfml-dev.org/forums/index.php#c3) or in an issue before?
+* [ ] Does the code follow the SFML [Code Style Guide](https://www.sfml-dev.org/style.php)?
+* [ ] Have you provided some example/test code for your changes?
+* [ ] If you have additional steps which need to be performed list them as tasks!
+
+----
+
+## Description
+
+Please describe your pull request.
+
+This PR is related to the issue #
+
+## Tasks
+
+* [ ] Tested on Linux
+* [ ] Tested on Windows
+* [ ] Tested on macOS
+* [ ] Tested on iOS
+* [ ] Tested on Android
+
+## How to test this PR?
+
+Describe how to best test these changes. Please provide a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve) if possible, you can use the follow template as a start:
+
+```cpp
+#include <SFML/Graphics.hpp>
+
+int main()
+{
+ sf::RenderWindow window(sf::VideoMode(1280, 720), "Minimal, complete and verifiable example");
+ window.setFramerateLimit(60);
+
+ while (window.isOpen())
+ {
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ if (event.type == sf::Event::Closed)
+ window.close();
+ }
+
+ window.clear();
+ window.display();
+ }
+}
+``` \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7914ac..bb30b46 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,9 @@
-cmake_minimum_required(VERSION 2.8.3)
+# CMake's built-in Android support requires 3.7.0
+if(CMAKE_SYSTEM_NAME MATCHES "Android")
+ cmake_minimum_required(VERSION 3.7.2)
+else()
+ cmake_minimum_required(VERSION 3.0.2)
+endif()
# define a macro that helps defining an option
macro(sfml_set_option var default type docstring)
@@ -16,25 +21,28 @@ sfml_set_option(CMAKE_BUILD_TYPE Release STRING "Choose the type of build (Debug
# Suppress Cygwin legacy warning
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
-# set Android specific options
-
-# define the minimum API level to be used
-sfml_set_option(ANDROID_API_MIN 9 STRING "Choose the Android API level to be used (minimum 9)")
-# mirror the setting for the toolchain file
-set(ANDROID_NATIVE_API_LEVEL ${ANDROID_API_MIN})
-
-# define the path to the Android NDK
-sfml_set_option(ANDROID_NDK "$ENV{ANDROID_NDK}" PATH "Path to the Android NDK")
-
-# define the STL implementation to be used
-sfml_set_option(ANDROID_STL c++_shared STRING "Choose the STL implementation to be used (experimental)")
-
-# default the ABI to ARM v7a for hardware floating point
-if(NOT ANDROID_ABI)
- set(ANDROID_ABI armeabi-v7a)
+# Suppress Mac OS X RPATH warnings and adopt new related behaviors
+cmake_policy(SET CMP0042 NEW)
+if (NOT CMAKE_VERSION VERSION_LESS 3.9)
+ cmake_policy(SET CMP0068 NEW)
endif()
-#end of Android specific options
+# add some default value for some additional macOS variable
+# note that those variables are ignored on other systems
+if(NOT CMAKE_OSX_ARCHITECTURES)
+ set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "macOS architecture to build; 64-bit is expected" FORCE)
+endif()
+if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.7" CACHE STRING "macOS deployement target; 10.7+ is expected" FORCE)
+endif()
+if(NOT CMAKE_OSX_SYSROOT)
+ # query the path to the default SDK, will fail on non-macOS, but it's okay.
+ execute_process(COMMAND xcodebuild -sdk macosx -version Path
+ COMMAND head -n 1
+ COMMAND tr -d '\n'
+ OUTPUT_VARIABLE CMAKE_OSX_SYSROOT
+ ERROR_QUIET)
+endif()
# project name
project(SFML)
@@ -44,11 +52,8 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake)
# setup version numbers
set(VERSION_MAJOR 2)
-set(VERSION_MINOR 4)
-set(VERSION_PATCH 2)
-
-# add the SFML header path
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+set(VERSION_MINOR 5)
+set(VERSION_PATCH 0)
# add an option for choosing the build type (shared or static)
if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID))
@@ -62,39 +67,46 @@ else()
endif()
# add an option for building the examples
-if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID))
+if(NOT SFML_OS_ANDROID)
sfml_set_option(SFML_BUILD_EXAMPLES FALSE BOOL "TRUE to build the SFML examples, FALSE to ignore them")
else()
set(SFML_BUILD_EXAMPLES FALSE)
endif()
+# add options to select which modules to build
+sfml_set_option(SFML_BUILD_WINDOW TRUE BOOL "TRUE to build SFML's Window module. This setting is ignored, if the graphics module is built.")
+sfml_set_option(SFML_BUILD_GRAPHICS TRUE BOOL "TRUE to build SFML's Graphics module.")
+sfml_set_option(SFML_BUILD_AUDIO TRUE BOOL "TRUE to build SFML's Audio module.")
+sfml_set_option(SFML_BUILD_NETWORK TRUE BOOL "TRUE to build SFML's Network module.")
+
# add an option for building the API documentation
sfml_set_option(SFML_BUILD_DOC FALSE BOOL "TRUE to generate the API documentation, FALSE to ignore it")
# add an option for choosing the OpenGL implementation
-sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation")
+if(SFML_BUILD_WINDOW)
+ sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation")
+endif()
# Mac OS X specific options
if(SFML_OS_MACOSX)
# add an option to build frameworks instead of dylibs (release only)
sfml_set_option(SFML_BUILD_FRAMEWORKS FALSE BOOL "TRUE to build SFML as frameworks libraries (release only), FALSE to build according to BUILD_SHARED_LIBS")
- # add an option to let the user specify a custom directory for frameworks installation (SFML, FLAC, ...)
- sfml_set_option(CMAKE_INSTALL_FRAMEWORK_PREFIX "/Library/Frameworks" STRING "Frameworks installation directory")
+ # add an option to let the user specify a custom directory for external frameworks installation
+ sfml_set_option(SFML_DEPENDENCIES_INSTALL_PREFIX "/Library/Frameworks" PATH "External frameworks (FLAC, Freetype, Vorbis, ...) installation directory")
# add an option to automatically install Xcode templates
sfml_set_option(SFML_INSTALL_XCODE_TEMPLATES FALSE BOOL "TRUE to automatically install the Xcode templates, FALSE to do nothing about it. The templates are compatible with Xcode 4 and 5.")
+else()
+ # add an option to let the user specify a custom directory for external libraries installation
+ sfml_set_option(SFML_DEPENDENCIES_INSTALL_PREFIX "." PATH "External libraries (FLAC, Freetype, Vorbis, ...) installation directory")
endif()
# Android options
if(SFML_OS_ANDROID)
# make sure there's the android library available
- if (${ANDROID_API_MIN} LESS 9)
- message(FATAL_ERROR "Android API level must be equal or greater than 9. Please adjust the CMake variable 'ANDROID_API_MIN'.")
- endif()
-
- if(NOT ANDROID_NDK)
- message(FATAL_ERROR "The Android NDK couldn't be found. Please adjust the CMake variable 'ANDROID_NDK' to point to the NDK directory.")
+ if (CMAKE_ANDROID_API LESS 14)
+ message(FATAL_ERROR "Android API level (${CMAKE_ANDROID_API}) must be equal or greater than 14.")
endif()
# CMake doesn't support defining the STL to be used with Nsight Tegra, so warn the user
@@ -103,31 +115,82 @@ if(SFML_OS_ANDROID)
endif()
# install everything in $NDK/sources/ because this path is appended by the NDK (convenient)
- set(CMAKE_INSTALL_PREFIX ${ANDROID_NDK}/sources/sfml)
+ set(CMAKE_INSTALL_PREFIX ${CMAKE_ANDROID_NDK}/sources/third_party/sfml)
# we install libs in a subdirectory named after the ABI (lib/mips/*.so)
- set(LIB_SUFFIX "/${ANDROID_ABI}")
+ set(LIB_SUFFIX "/${CMAKE_ANDROID_ARCH_ABI}")
# pass shared STL configuration (if any)
- if (ANDROID_STL MATCHES "_shared")
- add_definitions("-DSTL_LIBRARY=${ANDROID_STL}")
+ if (CMAKE_ANDROID_STL_TYPE MATCHES "_shared")
+ add_definitions("-DSTL_LIBRARY=${CMAKE_ANDROID_STL_TYPE}")
+ # if(NOT CMAKE_ANDROID_STL_TYPE MATCHES "c\\+\\+_shared")
+ # message("Android: Using ${CMAKE_ANDROID_STL_TYPE} as STL. Set CMAKE_ANDROID_STL_TYPE to c++_shared, if there are any issues.")
+ # endif()
+ else()
+ # message(WARNING "Android: You're using a static STL (${CMAKE_ANDROID_STL_TYPE}). Set CMAKE_ANDROID_STL_TYPE to c++_shared, if there are any issues.")
endif()
+ # let the user switch ABIs
+ set(ANDROID_ABI "armeabi-v7a" CACHE STRING "Look at the NDK docs for currently supported ABIs")
+
# this is a workaround to compile sfml-activity without the stl library as a dependency
# we save the original compilation command line to restore it later in Macro.cmake
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STL ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STL "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
-else()
- unset(ANDROID_ABI CACHE)
- unset(ANDROID_API_MIN CACHE)
- unset(ANDROID_STL CACHE)
- unset(ANDROID_NATIVE_API_LEVEL CACHE)
- unset(ANDROID_NDK CACHE)
endif()
-# define SFML_STATIC if the build type is not set to 'shared'
-if(NOT BUILD_SHARED_LIBS)
- add_definitions(-DSFML_STATIC)
+# Install directories
+# For miscellaneous files
+if(SFML_OS_WINDOWS OR SFML_OS_IOS)
+ set(DEFAULT_INSTALL_MISC_DIR .)
+elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
+ set(DEFAULT_INSTALL_MISC_DIR share/SFML)
+elseif(SFML_OS_MACOSX)
+ set(DEFAULT_INSTALL_MISC_DIR /usr/local/share/SFML)
+elseif(SFML_OS_ANDROID)
+ set(DEFAULT_INSTALL_MISC_DIR ${CMAKE_ANDROID_NDK}/sources/third_party/sfml)
+endif()
+# add an option to let the user specify a custom directory for doc, examples, licence, readme and other miscellaneous files
+sfml_set_option(SFML_MISC_INSTALL_PREFIX "${DEFAULT_INSTALL_MISC_DIR}" PATH "Prefix installation path for miscellaneous files")
+
+
+# force building sfml-window, if sfml-graphics module is built
+if(SFML_BUILD_GRAPHICS AND NOT SFML_BUILD_WINDOW)
+ message(WARNING "You're trying to build SFML's Graphics module without the Window module. Forcing building of the Window module as a dependency.")
+ set(SFML_BUILD_WINDOW TRUE)
+endif()
+
+# allow not using bundled dependencies with a switch
+# (except for stb_image)
+# yes this is horrible, but GLOB_RECURSE sucks
+sfml_set_option(SFML_USE_SYSTEM_DEPS FALSE BOOL "TRUE to use system dependencies, FALSE to use the bundled ones.")
+if(SFML_USE_SYSTEM_DEPS)
+ if(SFML_INSTALL_XCODE_TEMPLATES)
+ message(FATAL_ERROR "XCode templates installation cannot be used with the SFML_USE_SYSTEM_DEPS option (the bundled frameworks are required.)")
+ endif()
+
+ file(GLOB_RECURSE DEP_LIBS "${CMAKE_SOURCE_DIR}/extlibs/libs*/*")
+ file(GLOB_RECURSE DEP_BINS "${CMAKE_SOURCE_DIR}/extlibs/bin*/*")
+ file(GLOB_RECURSE DEP_HEADERS "${CMAKE_SOURCE_DIR}/extlibs/headers/*")
+
+ foreach(DEP_FILE ${DEP_LIBS} ${DEP_BINS} ${DEP_HEADERS})
+ get_filename_component(DEP_DIR ${DEP_FILE} PATH)
+
+ if(NOT DEP_DIR MATCHES "/stb_image(/|$)")
+ set(CMAKE_IGNORE_PATH ${CMAKE_IGNORE_PATH} ${DEP_DIR})
+ endif()
+
+ get_filename_component(DEP_PARENT_DIR ${DEP_DIR} PATH)
+ while(NOT DEP_PARENT_DIR STREQUAL "${CMAKE_SOURCE_DIR}/extlibs")
+ if(NOT DEP_DIR MATCHES "/stb_image(/|$)")
+ set(CMAKE_IGNORE_PATH ${CMAKE_IGNORE_PATH} ${DEP_PARENT_DIR})
+ endif()
+
+ get_filename_component(DEP_PARENT_DIR ${DEP_PARENT_DIR} PATH)
+ endwhile()
+ endforeach()
+
+ list(REMOVE_DUPLICATES CMAKE_IGNORE_PATH)
endif()
# Visual C++: remove warnings regarding SL security and algorithms on pointers
@@ -193,18 +256,22 @@ if(SFML_OS_MACOSX)
endif()
# only the default architecture (i.e. 64-bit) is supported
- if(CMAKE_OSX_ARCHITECTURES AND NOT "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")
+ if(NOT CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
message(FATAL_ERROR "Only 64-bit architecture is supported")
- return()
endif()
-
+
+ # Ensure macOS 10.7+ is used
+ if(CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.7")
+ message(FATAL_ERROR "macOS 10.7 or greater is required for the deployment target.")
+ endif()
+
# configure Xcode templates
set(XCODE_TEMPLATES_ARCH "\$(NATIVE_ARCH_ACTUAL)")
endif()
-if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
+if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
set(PKGCONFIG_DIR lib${LIB_SUFFIX}/pkgconfig)
- if(SFML_OS_FREEBSD)
+ if(SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
set(PKGCONFIG_DIR libdata/pkgconfig)
endif()
if(BUILD_SHARED_LIBS)
@@ -239,6 +306,19 @@ if(SFML_BUILD_DOC)
add_subdirectory(doc)
endif()
+sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES FALSE BOOL "TRUE to automatically install pkg-config files so other projects can find SFML")
+
+if(SFML_OS_SUPPORTS_PKGCONFIG OR SFML_INSTALL_PKGCONFIG_FILES)
+ foreach(sfml_module IN ITEMS all system window graphics audio network)
+ CONFIGURE_FILE(
+ "tools/pkg-config/sfml-${sfml_module}.pc.in"
+ "tools/pkg-config/sfml-${sfml_module}.pc"
+ @ONLY)
+ INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pkg-config/sfml-${sfml_module}.pc"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/${SFML_OS_PKGCONFIG_DIR}")
+ endforeach()
+endif()
+
# setup the install rules
if(NOT SFML_BUILD_FRAMEWORKS)
install(DIRECTORY include
@@ -270,6 +350,9 @@ else()
# create SFML.framework
add_library(SFML ${SFML_SOURCES})
+ # set the target flags to use the appropriate C++ standard library
+ sfml_set_stdlib(SFML)
+
# edit target properties
set_target_properties(SFML PROPERTIES
FRAMEWORK TRUE
@@ -279,82 +362,126 @@ else()
MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
PUBLIC_HEADER "${SFML_HEADERS}")
- # add the remaining headers
- add_custom_command(TARGET SFML
- POST_BUILD
- COMMAND cp -r ${PROJECT_SOURCE_DIR}/include/SFML/* $<TARGET_FILE_DIR:SFML>/Headers)
+ # add the non-optional SFML headers
+ add_custom_command(TARGET SFML POST_BUILD COMMAND cp -r
+ ${PROJECT_SOURCE_DIR}/include/SFML/Config.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/OpenGL.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/GpuPreference.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/System.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/Main.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/System
+ $<TARGET_FILE_DIR:SFML>/Headers)
+
+ # add window module headers if enabled
+ if(SFML_BUILD_WINDOW)
+ add_custom_command(TARGET SFML POST_BUILD COMMAND cp -r
+ ${PROJECT_SOURCE_DIR}/include/SFML/Window.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/Window
+ $<TARGET_FILE_DIR:SFML>/Headers)
+ endif()
+
+ # add network module headers if enabled
+ if(SFML_BUILD_NETWORK)
+ add_custom_command(TARGET SFML POST_BUILD COMMAND cp -r
+ ${PROJECT_SOURCE_DIR}/include/SFML/Network.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/Network
+ $<TARGET_FILE_DIR:SFML>/Headers)
+ endif()
+
+ # add graphics module headers if enabled
+ if(SFML_BUILD_GRAPHICS)
+ add_custom_command(TARGET SFML POST_BUILD COMMAND cp -r
+ ${PROJECT_SOURCE_DIR}/include/SFML/Graphics.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/Graphics
+ $<TARGET_FILE_DIR:SFML>/Headers)
+ endif()
+
+ # add audio module headers if enabled
+ if(SFML_BUILD_AUDIO)
+ add_custom_command(TARGET SFML POST_BUILD COMMAND cp -r
+ ${PROJECT_SOURCE_DIR}/include/SFML/Audio.hpp
+ ${PROJECT_SOURCE_DIR}/include/SFML/Audio
+ $<TARGET_FILE_DIR:SFML>/Headers)
+ endif()
# adapt install directory to allow distributing dylibs/frameworks in user's frameworks/application bundle
# NOTE: it's not required to link against SFML.framework
- set_target_properties(SFML PROPERTIES
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@rpath")
+ set_target_properties(SFML PROPERTIES INSTALL_NAME_DIR "@rpath")
+ if(NOT CMAKE_SKIP_BUILD_RPATH)
+ if (CMAKE_VERSION VERSION_LESS 3.9)
+ set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
+ else()
+ set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_NAME_DIR TRUE)
+ endif()
+ endif()
# install rule
install(TARGETS SFML
- FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX}
+ FRAMEWORK DESTINATION "."
COMPONENT devel)
endif()
-install(FILES license.txt DESTINATION ${INSTALL_MISC_DIR})
-install(FILES readme.txt DESTINATION ${INSTALL_MISC_DIR})
-if(NOT SFML_OS_ANDROID)
- install(FILES cmake/Modules/FindSFML.cmake DESTINATION ${INSTALL_MISC_DIR}/cmake/Modules)
-endif()
+install(FILES license.md DESTINATION ${SFML_MISC_INSTALL_PREFIX})
+install(FILES readme.md DESTINATION ${SFML_MISC_INSTALL_PREFIX})
# install 3rd-party libraries and tools
if(SFML_OS_WINDOWS)
- # install the binaries of SFML dependencies
- if(ARCH_32BITS)
- install(DIRECTORY extlibs/bin/x86/ DESTINATION bin)
- if(SFML_COMPILER_MSVC AND SFML_MSVC_VERSION LESS 14)
- install(DIRECTORY extlibs/libs-msvc/x86/ DESTINATION lib)
- elseif(SFML_COMPILER_MSVC)
- install(DIRECTORY extlibs/libs-msvc-universal/x86/ DESTINATION lib)
- else()
- install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION lib)
- endif()
- elseif(ARCH_64BITS)
- install(DIRECTORY extlibs/bin/x64/ DESTINATION bin)
- if(SFML_COMPILER_MSVC AND SFML_MSVC_VERSION LESS 14)
- install(DIRECTORY extlibs/libs-msvc/x64/ DESTINATION lib)
- elseif(SFML_COMPILER_MSVC)
- install(DIRECTORY extlibs/libs-msvc-universal/x64/ DESTINATION lib)
- else()
- install(DIRECTORY extlibs/libs-mingw/x64/ DESTINATION lib)
+ if(NOT SFML_USE_SYSTEM_DEPS)
+ # install the binaries of SFML dependencies
+ if(ARCH_32BITS)
+ install(DIRECTORY extlibs/bin/x86/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/bin)
+ if(SFML_COMPILER_MSVC AND SFML_MSVC_VERSION LESS 14)
+ install(DIRECTORY extlibs/libs-msvc/x86/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ elseif(SFML_COMPILER_MSVC)
+ install(DIRECTORY extlibs/libs-msvc-universal/x86/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ else()
+ install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ endif()
+ elseif(ARCH_64BITS)
+ install(DIRECTORY extlibs/bin/x64/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/bin)
+ if(SFML_COMPILER_MSVC AND SFML_MSVC_VERSION LESS 14)
+ install(DIRECTORY extlibs/libs-msvc/x64/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ elseif(SFML_COMPILER_MSVC)
+ install(DIRECTORY extlibs/libs-msvc-universal/x64/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ else()
+ install(DIRECTORY extlibs/libs-mingw/x64/ DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX}/lib)
+ endif()
endif()
endif()
elseif(SFML_OS_MACOSX)
-
# install extlibs dependencies only when used
- if("${FLAC_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/FLAC.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/FLAC.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
+ if(SFML_BUILD_GRAPHICS)
+ if(FREETYPE_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/freetype.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/freetype.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
endif()
- if("${FREETYPE_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/freetype.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/freetype.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
- endif()
+ if(SFML_BUILD_AUDIO)
+ if(FLAC_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/FLAC.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/FLAC.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
- if("${OGG_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/ogg.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/ogg.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
- endif()
+ if(OGG_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/ogg.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/ogg.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
- if("${VORBIS_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbis.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/vorbis.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
- endif()
+ if(VORBIS_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbis.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/vorbis.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
- if("${VORBISENC_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbisenc.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/vorbisenc.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
- endif()
+ if(VORBISENC_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbisenc.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/vorbisenc.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
- if("${VORBISFILE_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbisfile.framework")
- install(DIRECTORY extlibs/libs-osx/Frameworks/vorbisfile.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
- endif()
+ if(VORBISFILE_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/vorbisfile.framework")
+ install(DIRECTORY extlibs/libs-osx/Frameworks/vorbisfile.framework DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
- if("${OPENAL_LIBRARY}" STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/OpenAL.framework")
- install(DIRECTORY "${OPENAL_LIBRARY}" DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX})
+ if(OPENAL_LIBRARY STREQUAL "${SFML_SOURCE_DIR}/extlibs/libs-osx/Frameworks/OpenAL.framework")
+ install(DIRECTORY "${OPENAL_LIBRARY}" DESTINATION ${SFML_DEPENDENCIES_INSTALL_PREFIX})
+ endif()
endif()
# install the Xcode templates if requested
@@ -375,21 +502,34 @@ elseif(SFML_OS_MACOSX)
elseif(SFML_OS_IOS)
# fix CMake install rules broken for iOS (see http://public.kitware.com/Bug/view.php?id=12506)
- if(SFML_OS_IOS)
- install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/\$ENV{CONFIGURATION}/" DESTINATION lib${LIB_SUFFIX})
- endif()
+ install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/\$ENV{CONFIGURATION}/" DESTINATION lib${LIB_SUFFIX})
+
+ if(NOT SFML_USE_SYSTEM_DEPS)
+ # since the iOS libraries are built as static, we must install the SFML dependencies
+ # too so that the end user can easily link them to its final application
+ if(SFML_BUILD_GRAPHICS)
+ install(FILES extlibs/libs-ios/libfreetype.a DESTINATION lib)
+ endif()
- # since the iOS libraries are built as static, we must install the SFML dependencies
- # too so that the end user can easily link them to its final application
- install(FILES extlibs/libs-ios/libfreetype.a extlibs/libs-ios/libjpeg.a DESTINATION lib)
+ if(SFML_BUILD_AUDIO)
+ install(FILES extlibs/libs-ios/libflac.a
+ extlibs/libs-ios/libvorbis.a
+ extlibs/libs-ios/libogg.a
+ DESTINATION lib)
+ endif()
+ endif()
elseif(SFML_OS_ANDROID)
- # install extlibs
- install(DIRECTORY extlibs/libs-android/${ANDROID_ABI} DESTINATION extlibs/lib)
- install(FILES extlibs/Android.mk DESTINATION extlibs)
+ if(NOT SFML_USE_SYSTEM_DEPS)
+ # install extlibs
+ install(DIRECTORY extlibs/libs-android/${CMAKE_ANDROID_ARCH_ABI} DESTINATION extlibs/lib)
+ install(FILES extlibs/Android.mk DESTINATION extlibs)
+ endif()
# install Android.mk so the NDK knows how to set up SFML
install(FILES src/SFML/Android.mk DESTINATION .)
endif()
+
+sfml_export_targets()
diff --git a/CONTRIBUTING b/CONTRIBUTING
deleted file mode 100644
index fae5de0..0000000
--- a/CONTRIBUTING
+++ /dev/null
@@ -1,16 +0,0 @@
-Contribution Guidelines
-=======================
-
-You would like to see a feature implemented or a bug fixed in SFML? Great!
-Contributions to SFML are highly appreciated, be it in the form of general
-ideas, concrete suggestions or code patches.
-
-A few guiding rules have been set up on the SFML website that you should be
-aware of before opening an Issue or Pull Request. They will help you focus
-on the important stuff and prevent you from losing (y)our time with requests
-that are out of SFML's scope, known issues, and so on.
-
- http://www.sfml-dev.org/contribute.php
-
-Those rules cover the general scope defined for this project, a coding
-style, and a precise procedure to report bugs or suggest new features.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..ce2b66c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,7 @@
+# Contribution Guidelines
+
+You would like to see a feature implemented or a bug fixed in SFML? Great! Contributions to SFML are highly appreciated, be it in the form of general ideas, concrete suggestions or code patches.
+
+[A few guiding rules have been set up on the SFML website](https://www.sfml-dev.org/contribute.php) that you should be aware of before opening an Issue or Pull Request. They will help you focus on the important stuff and prevent you from losing (y)our time with requests that are out of SFML's scope, known issues, and so on.
+
+Those rules cover the general scope defined for this project, a coding style, and a precise procedure to report bugs or suggest new features.
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000..c51ee3a
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,654 @@
+# Changelog
+
+## SFML 2.5.0
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.5.0
+
+### General
+
+ * Replaced FindSFML.cmake with SFMLConfig.cmake (#1335)
+ * Markdown'd and updated readme, changelog, contributing and license files (#1196, #1368, #1317)
+ * Improve packaging support (#1173)
+ * Added Tagfile generation and search (#1327)
+ * Added CMake variables to select the modules to be built (#798, #800)
+ * Do not install extlibs if `SFML_USE_SYSTEM_DEPS` is true (#1236, #1237)
+ * Fixed various type conversion/comparison warnings (#1325)
+ * [Android] Increased minimum API version to 14 (#1362)
+ * [Android] Removed custom toolchain and added support for the newest NDK version and Gradle (#1350, #1393)
+ * [iOS] Updated the binary libs from exlibs/libs-ios (#1207, #1209)
+ * [iOS] Use a CMake toolchain file for iOS build (#1268, #1269)
+ * [iOS] Install extlibs if needed (#1348)
+ * [iOS] Drop 32 bit support (#1374)
+ * [iOS] Force correct iOS architecture for cmake (#1373, #1377)
+ * [iOS] Added iOS example (#1378)
+ * [macOS] Fixed launch of cocoa examples (#1334)
+ * [macOS] Improved application signing process (#1020, #1036, #1194)
+ * [macOS] Improved CMake script (#1215, #1371)
+ * [macOS] Use `-stdlib=libc++` (#1361)
+ * [OpenBSD] Added support for OpenBSD (#1330)
+
+### System
+
+**Bugfixes**
+
+ * Added protected destructor to `sf::NonCopyable` to prevent possible resource leaks (#1125, #1161)
+ * Fixed crash when `sf::Clock` is constructed in a global scope (#1258)
+
+### Window
+
+**Features**
+
+ * Implemented Cursor API (#269, #784, #827)
+ * Implemented Clipboard API (#715, #1204, #1221)
+ * Renamed a few key codes (#1395)
+ * Added joystick example (#1363)
+ * [Windows] Added support for interfacing with joysticks via DirectInput when it is available (#1251, #1326)
+ * [Windows] Fix discrete GPU preference symbols being exported from the wrong place (#1192, #1406)
+
+**Bugfixes**
+
+ * [Android] Return correct key code for delete/backspace (#1309, #1362)
+ * [iOS] Don't need to find vorbisfile or vorbisenc (#1347)
+ * [Linux] Fixed `sf::Window::getPosition()` returning incorrect position because of differences in window managers (#1228, #1266)
+ * [Linux] Fix X11 key repeat handling not filtering out events from other windows (#1223, #1230, #1291)
+ * [Linux] Restore fullscreen of a non-visible window (#1339)
+ * [macOS] Fixed window menu not working (#1091, #1180, #1193)
+ * [macOS] Fixed crash with application messing hardware detection e.g. TeamViewer (#1323)
+ * [macOS] Added support for (some) Hat/POV axis (#1248)
+ * [Windows] Prevent uninitialized read by zeroing memory (#1264)
+ * [Windows] Fixed modifier keys handling (#1357)
+
+### Graphics
+
+**Features**
+
+ * Implemented additional line spacing and letter spacing in `sf::Text` (#928, #1366)
+ * Added `sf::VertexBuffer` class (#1308)
+ * Added GPU local texture copying support, allowing performance optimizations and texture swapping (#1119, #1319, #1320)
+ * Optimize performance by skipping `glTexCoordPointer()` call if not needed (#1015)
+ * Generate shape outline vertices only if necessary (#925, #1356)
+ * Removed dependency to libjpeg, stb_image_write now supports writing JPEG files (#1278, #1279)
+ * Enable comparing `sf::Transform` and optimize resetting OpenGL back to the identity matrix (#1298)
+ * Added missing `setActive()` virtual method to `sf::RenderTarget` (#1157)
+ * Updated stb_image to v2.16 and stb_image_write to v1.07 (#1270)
+ * Added `sf::RenderTexture` stencil and multisampling support (#1274, #1285)
+ * Added example demonstrating `sf::VertexBuffer`, `sf::Shader` and `sf::Thread` usage (#1352)
+ * Optimized `sf::RenderTexture` performance (#1379)
+
+**Bugfixes**
+
+ * Properly free memory in `sf::Font::cleanup()` (#1119)
+ * Fixed memory leak in `sf::Font` (#1216)
+ * Fix OpenGL texture coordinate pointer not being updated correctly under certain conditions (#1297)
+ * Fix for broken text when the font is reloaded (#1345)
+ * Fix memory leak in `sf::Text` (#1233, #1360)
+ * Fixed strict aliasing punning warning when generating the key of a glyph in Font.cpp (#1187, #1396)
+ * Fixed OpenGL version string being parsed incorrectly on some platforms (#1249, #1390)
+ * [macOS] Worked around render target bug (#1132, #1342)
+ * [Windows] Replaced time-based joystick poll with a hardware event handler (#1179, #1195, #1198, #1199, #1421)
+
+### Audio
+
+**Features**
+
+ * Added loop point support to `sf::Music` (#177, #629)
+ * Added support for the extensible PCM wave file format (#1296)
+ * [iOS] Enable audio module (#1338)
+
+**Bugfixes**
+
+ * Fixed inconsistent seek behavior in `sf::SoundStream` (#1118)
+ * Fixed stack overflow in `sf::SoundStream::fillAndPushBuffer()` (#1154)
+ * Fixed seeking quirks in the FLAC reader (#966, #1162)
+ * Allow polymorphism with `sf::SoundSource` (#1185)
+ * Fixed WAV file writer writing wrong header values (#1280, #1281)
+ * Small bugfix to argument of `alcCaptureOpenDevice()` (#1304, #1305)
+ * [iOS] Find OpenAL correctly (#1263, #1376)
+ * [Windows] Updated OpenAL Soft to 1.18.1 fixing crashes (#1247, #1260)
+
+### Network
+
+**Features**
+
+ * Add append/overwrite parameter to Ftp::upload (#1072, #1399)
+
+**Bugfixes**
+
+ * Fixed wrong condition for building network support (#1253)
+ * Changed TCP listen backlog from 0 to SOMAXCONN (#1369, #1407)
+ * Fixed socket reuse not conforming to documentation (#1346, #1408)
+
+## SFML 2.4.2
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.4.2
+
+### System
+
+**Bugfixes**
+
+ * [Windows] Removed thread affinity changes in sf::Clock (#1107)
+
+### Window
+
+**Bugfixes**
+
+ * Fixed bug where TransientContextLock would hang (#1165, #1172)
+ * [Linux] Fixed GLX extensions being loaded too late (#1183)
+ * [Linux] Fix wrong types passed to XChangeProperty (#1168, #1171)
+ * [Windows] Make context disabling via wglMakeCurrent more tolerant of broken drivers (#1186)
+
+### Graphics
+
+**Bugfixes**
+
+ * Optimized sf::Image::create and made it more exception safe (#1166)
+
+## SFML 2.4.1
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.4.1
+
+### General
+
+ * [kFreeBSD] Define SFML_OS_FREEBSD when compiling for kFreeBSD (#1129)
+ * [Windows] Added some simple messaging when trying to build under Cygwin (#1153)
+
+### Window
+
+**Bugfixes**
+
+ * Fixed stack overflow on GlContext creation with multiple threads (#989, #1002)
+ * Adjusted mouse cursor grab documentation (#1133)
+ * [iOS] Fixed orientation change not rescaling window size properly (#1049, #1050)
+ * [Linux] Fixed fullscreen issue (#921, #1138)
+ * [Linux] Switched from XCB back to Xlib for windowing (#1138)
+ * [Linux] Fixed window icon not showing up on some distros (#1087, #1088)
+ * [Linux] Fixed an issue where GNOME flags window unresponsive (#1089, #1138)
+ * [Linux] Fixed leak of XVisualInfo objects during GlxContext creation (#1135)
+ * [Linux] Fixed possible hang when setting visibility if external window sources (#1136)
+ * [macOS] Fixed inconsistency between doc and impl on macOS for the grab feature (#1133, #1148, #1150)
+ * [Windows] Fixed context memory leaks (#1143, #1002)
+
+### Graphics
+
+**Bugfixes**
+
+ * Adjusted uniform error message (#1131)
+ * Clarify documentation on Rect::contains function bounds (#1151)
+
+### Network
+
+**Bugfixes**
+
+ * Fixed a typo in comment for void unbind() (#1121)
+
+## SFML 2.4.0
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.4.0
+
+### General
+
+ * Added deprecation macro (#969)
+ * Fixed issues reported by Coverity Scan static analysis (#1064)
+ * Fixed some initialization issues reported by Cppcheck (#1008)
+ * Changed comment chars in FindSFML.cmake to # (#1090)
+ * Fixed some typos (#1098, #993, #1099, #956, #963, #979)
+ * Updated/fixed string comparisons in Config.cmake (#1102)
+ * Added the missing -s postfix for the RelWithDebInfo config (#1014)
+ * [Android] Fixed current Android compilation issues (#1116, #1111, #1079)
+ * [macOS] Update Xcode template material (#976, #968)
+ * [Windows] Added support for VS 2015 (#972)
+ * [Windows] Create and install PDB debug symbols alongside binaries (#1037)
+
+### Deprecated API
+
+ * sf::RenderWindow::capture(): Use a sf::Texture and its sf::Texture::update(const Window&) function and copy its contents into an sf::Image instead.
+ * sf::Shader::setParameter(): Use setUniform() instead.
+ * sf::Text::getColor(): There is now fill and outline colors instead of a single global color. Use getFillColor() or getOutlineColor() instead.
+ * sf::Text::setColor(): There is now fill and outline colors instead of a single global color. Use setFillColor() or setOutlineColor() instead.
+ * sf::LinesStrip: Use LineStrip instead.
+ * sf::TrianglesFan: Use TriangleFan instead.
+ * sf::TrianglesStrip: Use TriangleStrip instead.
+
+### System
+
+**Features**
+
+ * [Android] Added sf::getNativeActivity() (#1005, #680)
+
+**Bugfixes**
+
+ * Added missing <iterator> include in String.hpp (#1069, #1068)
+ * Fixed encoding of UTF-16 (#997)
+ * [Android] Fixed crash when trying to load a non-existing font file (#1058)
+
+### Window
+
+**Features**
+
+ * Added ability to grab cursor (#614, #394, #1107)
+ * Added Multi-GPU preference (#869, #867)
+ * Added support for sRGB capable framebuffers (#981, #175)
+ * [Linux, Windows] Improved OpenGL context creation (#884)
+ * [Linux, Windows] Added support for pbuffers on Windows and Unix (#885, #434)
+
+**Bugfixes**
+
+ * Updated platform-specific handle documentation (#961)
+ * [Android] Accept touch events from "multiple" devices (#954, #953)
+ * [Android] Copy the selected EGL context's settings to SFML (#1039)
+ * [Linux] Fixed modifiers causing sf::Keyboard::Unknown being returned (#1022, #1012)
+ * [macOS] Improved memory management on macOS (#962, #790)
+ * [macOS] Fixed crash when resizing a window to a zero-height/width size (#986, #984)
+ * [macOS] Use the mouse button constant instead of 0 to avoid a compiler error on macOS (#1035)
+ * [macOS] macOS improvement: warnings + bugfix + refactoring, the lot! (#1042)
+
+### Graphics
+
+**Features**
+
+ * Added support for outlined text (#840)
+ * Add support for geometry shaders (#886, #428)
+ * Feature/blend mode reverse subtract (#945, #944)
+ * Implemented support for mipmap generation (#973, #498, #123)
+ * Added new API to set shader uniforms (#983, #538)
+ * Rewrite RenderWindow::capture (#1001)
+
+**Bugfixes**
+
+ * Exporting some Glsl utility functions due to linking issues (#1044, #1046)
+ * Fixed missing initialisation of Font::m_stroker (#1059)
+ * Changed primitive types to be grammatically correct (#1095, #939)
+
+### Audio
+
+**Features**
+
+ * Implemented stereo audio recording (#1010)
+
+**Bugfixes**
+
+ * Added an assignment operator to SoundSource (#864)
+ * [macOS] Updates OpenAL-soft for macOS to version 1.17.2 (#1057, #900, #1000)
+ * Fixed a bug where vorbis can't handle large buffers (#1067)
+ * Added support for 24-bit .wav files (#958, #955)
+ * Fixed threading issue in sf::SoundRecorder (#1011)
+ * Made WAV file reader no longer assume that data chunk goes till end of file to prevent reading trailing metadata as samples (#1018)
+ * Fixed seeking in multi channel FLAC files (#1041, #1040)
+
+### Network
+
+**Features**
+
+ * Added optional argument on which address to bind (socket). (#850, #678)
+
+**Bugfixes**
+
+ * Fixed FTP directory listing blocking forever (#1086, #1025)
+
+## SFML 2.3.2
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.3.2
+
+### General
+
+ * Fixed an issue where FindSFML.cmake couldn't find older versions of SFML (#903)
+ * Robust alCheck and glCheck macros (#917)
+ * Fixed FindSFML.cmake to use the uppercase FLAC name (#923)
+ * Added a CONTRIBUTING file so GitHub shows a message when creating a new issue (#932)
+
+### Window
+
+**Bugfixes**
+
+ * [Linux] Fixed an issue where the keypad's key weren't being detected (#910)
+ * [Linux] Revert to Xlib event handling (#934)
+ * [Linux] Fixed `XK_*` inconsistency in InpuImpl.cpp (#947)
+ * [Linux] Fix `_NET_WM_PING` messages not being replied to properly (#947)
+
+### Graphics
+
+**Bugfixes**
+
+ * Fixed clear bug on RenderTextures (#915)
+ * Fixed image file extension detection (#929, #930, #931)
+ * Secure function against random data return (#935, #942)
+
+## SFML 2.3.1
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.3.1
+
+### Window
+
+**Bugfixes**
+
+ * [Android] Make sure a window still exists before trying to access its dimensions (#854)
+ * [Android] Added Android API level checks (#856)
+ * [Android] Updated the JNI/event handling code (#906)
+ * [Linux] Resized events are only spawned when the window size actually changes (#878, #893)
+ * [Linux] Whitelisted X SHAPE events (#879, #883)
+ * [Linux] Remap Unix keyboard when user changes layout (#895, #897)
+ * [Linux] Fix undefined behavior in ewmhSupported() (#892, #901)
+
+### Graphics
+
+**Bugfixes**
+
+ * Added support for GL_EXT_texture_edge_clamp for systems that don't expose GL_SGIS_texture_edge_clamp (#880, #882)
+
+### Audio
+
+**Bugfixes**
+
+ * [Android] Fixed audio files not loading (and possibly crashing) (#855, #887)
+
+## SFML 2.3
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.3
+
+### General
+
+ * Examples only link against sfml-main in release mode (#610, #766)
+ * Replaced unsigned int with std::size_t for array indices and sizes (#739)
+ * Fixed some issues with the Doxygen documentation (#750)
+ * Added support for EditorConfig (#751)
+ * Hide success message for CMake in quiet mode (#753)
+ * Improved documentation for statuses with sf::Ftp (#763)
+ * Moved stb_image into the extlibs directory (#795)
+ * Changed the SOVERSION to major.minor (#812)
+ * Fixed warnings about switch-statements (#863)
+ * Added missing includes in the general headers (#851)
+ * [Android] Updated toolchain file and dependencies (#791)
+ * [Linux] Fixed missing pthread dependency (#794)
+ * [macOS] Relaxed CMake installation rules regarding framework dependencies (#767)
+
+### Deprecated API
+
+ * sf::Event::MouseWheelEvent: This event is deprecated and potentially inaccurate. Use MouseWheelScrollEvent instead.
+
+### Window
+
+**Features**
+
+ * Added new events for handling high-precision scrolling (#95, #810, #837)
+ * Switched from Xlib to XCB (#200, #319, #694, #780, #813, #825)
+ * Added support for OpenGL 3 core context creation (#654, #779)
+
+**Bugfixes**
+
+ * Fixed glXSwapIntervalSGI being broken for some driver implementations (#727, #779)
+ * Fixed simultaneous context operations causing crashes on some AMD hardware (#778, #779)
+ * Fixed joystick identification (#809, #811)
+ * [iOS] Fixed various issues including stencil bits, device orientation and retina support (#748)
+ * [iOS] Fixed inconsistency between sf::Touch::getPosition and touch events (#875)
+ * [Linux] Fixed Alt+F4 not getting triggered in window mode (#274)
+ * [Linux] Fixed Unix joystick stuff (#838)
+ * [macOS] Fixed typo in JoystickImpl.cpp to prevent a crash (#762, #765)
+ * [macOS] Fixed an issue in InputImpl::getSFOpenGLViewFromSFMLWindow (#782, #792)
+
+### Graphics
+
+**Features**
+
+ * Replaced GLEW with loader generated by glLoadGen (#779)
+ * Added a new constructor to sf::Color that takes an sf::Uint32 (#722)
+ * Updated stb_image to v2.02 (#777)
+ * Updated FreeType to v2.5.5 (#799, #804)
+ * Added checks for software OpenGL (#870)
+
+**Bugfixes**
+
+ * Fixed GL_ARB_compatibility not being detected (#859)
+ * Fixed pixel format selection (#862)
+ * Bumped back the OpenGL version requirement to 1.1 (#858)
+
+### Audio
+
+**Features**
+
+ * Dropped libsndfile and started using Vorbis, FLAC and OGG directly (#604, #757)
+ * Added a FLAC file to the sound example (#815)
+
+**Bugfixes**
+
+ * Fixed access violation error in the destructor of sf::AudioDevice (#30, #602)
+ * [macOS] Fixed threading issue with sf::SoundStream and OpenAL (#541, #831)
+
+### Network
+
+**Bugfixes**
+
+ * Fixed sf::TcpSocket not handling partial sends properly (#749, #796)
+
+## SFML 2.2
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.2
+
+### General
+
+ * Support for iOS and Android platform (#410, #440)
+ * Various documentation corrections (#438, #496, #497, #714)
+ * Fixed support for compilers on Debian FreeBSD (#380, #578)
+ * Added support for Visual Studio 2013 and proper support for the TDM builds (#482)
+ * Fixed CMake problems related to FindSFML and cached variables (#637, #684)
+ * Switched and enforced LF line endings (#708, #712)
+ * Updated OpenAL to version 1.15.1 (d077210)
+ * Made compiler and OS variable names much clearer in CMake files (9b0ed30)
+ * Re-enabled RPATH feature (e157e7a)
+ * Slight adjustments to the examples (#737)
+ * [FreeBSD] Various configuration fixes (#577, #578)
+ * [Linux] Updated FindSFML.cmake to add UDev to SFML's dependencies (#728, #729, #734, #736)
+ * [macOS] Fixed incorrect symlink in freetype.framework (#519)
+ * [macOS] CMake module for correct dependencies (#548)
+ * [macOS] Fixed SFML target for Xcode (#595, #596)
+ * [macOS] Updated implementation, mainly reverting to non-ARC (#601)
+ * [macOS] Fixed memory leaks and dead store (#615)
+ * [macOS] Improved event handling and performance (#617)
+ * [macOS] Reduced memory usage (#672, #698)
+ * [macOS] macOS 10.10 support (#691, #699)
+ * [macOS] Improve flexibility of dependencies' locations (#713)
+ * [Windows] Removed the hack that copied external libraries into SFML static libraries (dbf01a7)
+
+### System
+
+**Features**
+
+ * Added substring and replace functions to sf::String (#21, #355)
+ * Added toUtfX to sf::String (#501)
+ * Added fromUtfX functions to set the internal data to a string by converting from another string in a fixed encoding (#196)
+ * Added modulo operator for sf::Time (#429, #430)
+ * Added division operator for sf::Time (#453)
+
+**Bugfixes**
+
+ * Ensured a high resolution for sf::sleep (#439, #475)
+ * [Windows] Fixed stack unalignment by two internal functions (#412)
+
+### Window
+
+**Features**
+
+ * Added window methods to request and to check focus (#518, #525, #613, #723, #735)
+ * Provide name, manufacturer ID and product ID via sf::Joystick (#152, #528)
+ * [FreeBSD] Joystick support (#477)
+ * [macOS] Improved integration with menus and dock actions (#11)
+ * [macOS] Support for OpenGL 3.2 (#84)
+ * [macOS] Improved fullscreen support (#343)
+ * [macOS] Added support for retina displays (#353, #388)
+ * [Windows] Removed support for Windows 9x (#469)
+ * [Windows] Fixed typo in Windows keyboard implementation (#516)
+
+**Bugfixes**
+
+ * sf::Window::create() now also resets framerate limit (#371)
+ * Fixed OpenGL context leak (#635, #705)
+ * Fixed various joystick problems (memory leak, accelerometer detected, code refactoring) (#660, #686, #742, #743)
+ * Optimized sf::Window::waitEvent a bit, no sleep if events are available at first try (ff555d6)
+ * [Linux] Output error message when XOpenDisplay() fails (#508, #616)
+ * [Linux] Resize window with setSize when sf::Style::Resize is set (#466)
+ * [Linux] Fixed broken key repeat on window recreation (#564, #567)
+ * [macOS] Fixed KeyReleased not being fired in fullscreen mode (#465)
+ * [macOS] Fixed an issue where disconnecting the keyboard would cause a crash (#467)
+ * [macOS] Fixed unexpected resizing behavior (#468)
+ * [macOS] Improved resizing windows (#474)
+ * [macOS] Fixed memory leak with sf::Window::create() (#484)
+ * [macOS] Fixed menu shortcuts in fullscreen on macOS (#527)
+ * [macOS] Improved cursor hiding (#703)
+ * [macOS] Fixed right click not detected with trackpads (#716, #730)
+ * [Windows] Fixed joystick POV values (ef1d29b)
+ * [Windows] Fixed Unicode inconsistency (#635)
+ * [Windows] Fixed Alt+F4 and mouse clicks issues (#437, #457)
+ * [Windows] Send MouseButtonReleased event when the mouse is outside of the window (#455, #457)
+ * [Windows] Fixed sf::Joystick wrong registry usage (#701, #702, #706)
+
+### Graphics
+
+**Features**
+
+ * Provide more information about the loaded font in sf::Font (#164)
+ * Implemented a more flexible blending system (#298)
+ * Added strikethrough text style (#243, #362, #682)
+ * Slight optimization for sf::Text::setString (#413)
+ * Added subtraction operator for sf::Color (#114, #145)
+ * Optimized sf::Image::flipVertically/flipHorizontally (#555)
+ * Changed sf::Font measurements from int to float to allow better underline drawing (#693)
+
+**Bugfixes**
+
+ * Improved text quality for small and pixelated fonts (#228)
+ * Yet another fix for Intel GPUs with sf::RenderTexture (#418)
+ * Removed VTab since it causes issues and doesn't have a use nowadays (#442, #445, #460, #588)
+ * Fixed broken BDF and PCF font formats (#448)
+ * Fixed compilation issue with newer versions of GCC for sf::Rect (#458)
+ * Fixed resetGLStates() not explicitly setting the default polygon mode (#480)
+ * Fixed division-by-zero in sf::RectangleShape (#499)
+ * Fixed potential memory leak in sf::Font (#509)
+ * Updated glext and removed glxext (#511, #583)
+ * Make sure texture unit 0 is active when resetting sf::RenderTarget states (#523, #591)
+ * Fixed texture rect computation in fonts (#669)
+ * Improved rendering of underlined text (#593)
+ * Avoided repeated output of error messages (#566)
+ * Fixed text rendered with vertical offset on ascent and font size mismatch (#576)
+ * Fixed rounding problem for viewports (#598)
+ * Fixed sf::Shader::isAvailable() possibly breaking context management (#211, #603, #608, #603)
+ * Fixed sf::Texture::getMaximumSize() possibly breaking context management (#666)
+ * Fixed various sf::Text rendering issues (#692, #699)
+ * The texture matrix is now reset in sf::Texture::bind(NULL) (7c4b058)
+ * [Windows] Fixed DPI scaling causing strange window behavior (#679, #681, #688)
+
+### Audio
+
+**Features**
+
+ * Added support for selecting the audio capture device (#220, #470)
+ * Make sf::SoundRecorder processing frequency configurable (#333)
+ * Added up vector to sf::Listener (#545)
+
+**Bugfixes**
+
+ * Prevented sf::SoundStream::setPlayingOffset() from restarting playing even when paused (#203, #592)
+ * Fixed sf::SoundBuffer contents not being able to be updated when still attached to sounds (#354, 367, #390, #589)
+ * Catch audio format error and prevent division by zero (#529)
+ * Fixed sf::SoundBuffer returning wrong duration for sounds containing more than ~4.3 million samples (2ff58ed)
+ * Optimized sf::Listener with a cache (d97e524)
+
+### Network
+
+**Features**
+
+ * Added support for PUT and DELETE in sf::Http (#257, #312, #607)
+ * Added support for chunked HTTP transfers (#296, #337)
+ * Added support for 64-bit integers in sf::Packet (#710)
+ * Made sf::Ftp::sendCommand() public (2c5cab5)
+
+**Bugfixes**
+
+ * Checked socket descriptor limit (#153, #628, #683)
+ * Fixed sf::TcpSocket::connect()'s switching from blocking to non-blocking mode on immediate connection success (#221)
+ * Fixed FTP download and upload file sizes being limited by available RAM (#565, #590)
+ * Fixed C++11 compiler warnings for sf::Uint8 (#731, #732)
+
+## SFML 2.1
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.1
+
+### General
+
+ * Updated the Window and OpenGL examples (got rid of GLU and immediate mode)
+
+### Window
+
+**Features**
+
+ * Now using inotify on Linux to avoid constantly polling joystick connections (#96)
+ * Add keypad return, equal and period keys support for macOS
+ * Improved mouse events on macOS regarding fullscreen mode
+ * Improved mouse events on macOS (#213, #277)
+ * Improved reactivity of setMousePosition on macOS (#290)
+ * Added support for right control key on macOS
+ * Improved TextEntered for macOS (#377)
+ * Improved the performances of Window::getSize() (the size is now cached)
+ * Added the WM_CLASS property to SFML windows on Linux
+ * Fake resize events are no longer sent when the window is moved, on Linux
+ * Pressing ALT or F10 on Windows no longer steals the focus
+
+**Bugfixes**
+
+ * Fixed MouseMove event sometimes not generated when holding left button on Windows (#225)
+ * Fixed ContextSettings ignored when creating a 3.x/4.x OpenGL context on Linux (#258)
+ * Fixed ContextSettings ignored on Linux when creating a window (#35)
+ * Fixed windows bigger than the desktop not appearing on Windows (#215)
+ * Fixed KeyRelease events sometimes not reported on Linux (#404)
+ * Fixed mouse moved event on macOS when dragging the cursor (#277)
+ * Fixed KeyRelease event with CMD key pressed (#381)
+ * Fixed taskbar bugs on Windows (#328, #69)
+ * Fixed Window::getPosition() on Linux (#346)
+ * Unicode characters outside the BMP (> 0xFFFF) are now correctly handled on Windows (#366)
+
+### Graphics
+
+**Features**
+
+ * Checking errors in RenderTarget::pushGLStates() to avoid generating false error messages when user leaves unchecked OpenGL errors (#340)
+ * Optimized Shader::setParameter functions, by using a cache internally (#316, #358)
+
+**Bugfixes**
+
+ * Fixed bounding rect of sf::Text ignoring whitespaces (#216)
+ * Solved graphics resources not updated or corrupted when loaded in a thread (#411)
+ * Fixed white pixel showing on first character of sf::Text (#414)
+ * sf::Rect::contains and sf::Rect::intersects now handle rectangles with negative dimensions correctly (#219)
+ * Fixed Shape::setTextureRect not working when called before setTexture
+
+### Audio
+
+**Features**
+
+ * loadFromStream functions now explicitly reset the stream (seek(0)) before starting to read (#349)
+
+**Bugfixes**
+
+ * Added a workaround for a bug in the macOS implementation of OpenAL (unsupported channel count no properly detected) (#201)
+ * Fixed SoundBuffer::loadFromStream reading past the end of the stream (#214)
+
+### Network
+
+**Features**
+
+ * Replaced the deprecated gethostbyname with getaddrinfo (#47)
+ * Minor improvements to sf::Packet operators (now using strlen and wcslen instead of explicit loops) (#118)
+
+**Bugfixes**
+
+ * Fixed non-blocking connection with a sf::TcpSocket on Windows
+ * Fixed TCP packet data corruption in non-blocking mode (#402, #119)
+ * On Unix systems, a socket disconnection no longer stops the program with signal SIGPIPE (#72)
+
+## SFML 2.0
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.0
+
+No changelog available. *Everything changed.*
+
+## Older Releases
+
+See the website for changelogs of older releases: https://www.sfml-dev.org/changelog.php
diff --git a/changelog.txt b/changelog.txt
deleted file mode 100644
index 7b08dad..0000000
--- a/changelog.txt
+++ /dev/null
@@ -1,615 +0,0 @@
-SFML 2.4.2
-==========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.4.2
-
-System
-======
-
-Bugfixes
---------
-* [Windows] Removed thread affinity changes in sf::Clock (#1107)
-
-
-Window
-======
-
-Bugfixes
---------
-* Fixed bug where TransientContextLock would hang (#1165, #1172)
-* [Linux] Fixed GLX extensions being loaded too late (#1183)
-* [Linux] Fix wrong types passed to XChangeProperty (#1168 #1171)
-* [Windows] Make context disabling via wglMakeCurrent more tolerant of broken drivers (#1186)
-
-
-Graphics
-========
-
-Bugfixes
---------
-* Optimized sf::Image::create and made it more exception safe (#1166)
-
-
-
-SFML 2.4.1
-==========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.4.1
-
-General
-=======
-
-* [kFreeBSD] Define SFML_OS_FREEBSD when compiling for kFreeBSD (#1129)
-* [Windows] Added some simple messaging when trying to build under Cygwin (#1153)
-
-
-Window
-======
-
-Bugfixes
---------
-* Fixed stack overflow on GlContext creation with multiple threads (#989, #1002)
-* Adjusted mouse cursor grab documentation (#1133)
-* [iOS] Fixed orientation change not rescaling window size properly (#1049, #1050)
-* [Linux] Fixed fullscreen issue (#921, #1138)
-* [Linux] Switched from XCB back to Xlib for windowing (#1138)
-* [Linux] Fixed window icon not showing up on some distros (#1087, #1088)
-* [Linux] Fixed an issue where GNOME flags window unresponsive (#1089, #1138)
-* [Linux] Fixed leak of XVisualInfo objects during GlxContext creation (#1135)
-* [Linux] Fixed possible hang when setting visibility if external window sources (#1136)
-* [OS X] Fixed inconsistency between doc and impl on OS X for the grab feature (#1133, #1148, #1150)
-* [Windows] Fixed context memory leaks (#1143, #1002)
-
-
-Graphics
-========
-
-Bugfixes
---------
-* Adjusted uniform error message (#1131)
-* Clarify documentation on Rect::contains function bounds (#1151)
-
-
-Network
-=======
-
-Bugfixes
---------
-* Fixed a typo in comment for void unbind() (#1121)
-
-
-
-SFML 2.4.0
-==========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.4.0
-
-General
-=======
-
-* Added deprecation macro (#969)
-* Fixed issues reported by Coverity Scan static analysis (#1064)
-* Fixed some initialization issues reported by Cppcheck (#1008)
-* Changed comment chars in FindSFML.cmake to # (#1090)
-* Fixed some typos (#1098, #993, #1099, #956, #963, #979)
-* Updated/fixed string comparisons in Config.cmake (#1102)
-* Added the missing -s postfix for the RelWithDebInfo config (#1014)
-* [Android] Fixed current Android compilation issues (#1116, #1111, #1079)
-* [OS X] Update Xcode template material (#976, #968)
-* [Windows] Added support for VS 2015 (#972)
-* [Windows] Create and install PDB debug symbols alongside binaries (#1037)
-
-Deprecated API
-==============
-
-* sf::RenderWindow::capture(): Use a sf::Texture and its sf::Texture::update(const Window&) function and copy its contents into an sf::Image instead.
-* sf::Shader::setParameter(): Use setUniform() instead.
-* sf::Text::getColor(): There is now fill and outline colors instead of a single global color. Use getFillColor() or getOutlineColor() instead.
-* sf::Text::setColor(): There is now fill and outline colors instead of a single global color. Use setFillColor() or setOutlineColor() instead.
-* sf::LinesStrip: Use LineStrip instead.
-* sf::TrianglesFan: Use TriangleFan instead.
-* sf::TrianglesStrip: Use TriangleStrip instead.
-
-System
-======
-
-Features
---------
-* [Android] Added sf::getNativeActivity() (#1005, #680)
-
-Bugfixes
---------
-* Added missing <iterator> include in String.hpp (#1069, #1068)
-* Fixed encoding of UTF-16 (#997)
-* [Android] Fixed crash when trying to load a non-existing font file (#1058)
-
-
-Window
-======
-
-Features
---------
-* Added ability to grab cursor (#614, #394, #1107)
-* Added Multi-GPU preference (#869, #867)
-* Added support for sRGB capable framebuffers (#981, #175)
-* [Linux, Windows] Improved OpenGL context creation (#884)
-* [Linux, Windows] Added support for pbuffers on Windows and Unix (#885, #434)
-
-Bugfixes
---------
-* Updated platform-specific handle documentation (#961)
-* [Android] Accept touch events from "multiple" devices (#954, #953)
-* [Android] Copy the selected EGL context's settings to SFML (#1039)
-* [Linux] Fixed modifiers causing sf::Keyboard::Unknown being returned (#1022, #1012)
-* [OS X] Improved memory management on OS X (#962, #790)
-* [OS X] Fixed crash when resizing a window to a zero-height/width size (#986, #984)
-* [OS X] Use the mouse button constant instead of 0 to avoid a compiler error on OSX (#1035)
-* [OS X] OS X improvement: warnings + bugfix + refactoring, the lot! (#1042)
-
-
-Graphics
-========
-
-Features
---------
-* Added support for outlined text (#840)
-* Add support for geometry shaders (#886, #428)
-* Feature/blend mode reverse subtract (#945, #944)
-* Implemented support for mipmap generation (#973, #498, #123)
-* Added new API to set shader uniforms (#983, #538)
-* Rewrite RenderWindow::capture (#1001)
-
-Bugfixes
---------
-* Exporting some Glsl utility functions due to linking issues (#1044, #1046)
-* Fixed missing initialisation of Font::m_stroker (#1059)
-* Changed primitive types to be grammatically correct (#1095, #939)
-
-
-Audio
-=====
-
-Features
---------
-* Implemented stereo audio recording (#1010)
-
-Bugfixes
---------
-* Added an assignment operator to SoundSource (#864)
-* [OS X] Updates OpenAL-soft for OS X to version 1.17.2 (#1057, #900, #1000)
-* Fixed a bug where vorbis can't handle large buffers (#1067)
-* Added support for 24-bit .wav files (#958, #955)
-* Fixed threading issue in sf::SoundRecorder (#1011)
-* Made WAV file reader no longer assume that data chunk goes till end of file to prevent reading trailing metadata as samples (#1018)
-* Fixed seeking in multi channel FLAC files (#1041, #1040)
-
-Network
-=======
-
-Features
---------
-* Added optional argument on which address to bind (socket). (#850, #678)
-
-Bugfixes
---------
-* Fixed FTP directory listing blocking forever (#1086, #1025)
-
-
-
-SFML 2.3.2
-==========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3.2
-
-General
-=======
-
-* Fixed an issue where FindSFML.cmake couldn't find older versions of SFML (#903)
-* Robust alCheck and glCheck macros (#917)
-* Fixed FindSFML.cmake to use the uppercase FLAC name (#923)
-* Added a CONTRIBUTING file so GitHub shows a message when creating a new issue (#932)
-
-
-Window
-======
-
-Bugfixes
---------
-* [Linux] Fixed an issue where the keypad's key weren't being detected (#910)
-* [Linux] Revert to Xlib event handling (#934)
-* [Linux] Fixed XK_* inconsistency in InpuImpl.cpp (#947)
-* [Linux] Fix _NET_WM_PING messages not being replied to properly (#947)
-
-
-Graphics
-========
-
-Bugfixes
---------
-* Fixed clear bug on RenderTextures (#915)
-* Fixed image file extension detection (#929, #930, #931)
-* Secure function against random data return (#935, #942)
-
-
-
-SFML 2.3.1
-==========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3.1
-
-Window
-======
-
-Bugfixes
---------
-* [Android] Make sure a window still exists before trying to access its dimensions (#854)
-* [Android] Added Android API level checks (#856)
-* [Android] Updated the JNI/event handling code (#906)
-* [Linux] Resized events are only spawned when the window size actually changes (#878, #893)
-* [Linux] Whitelisted X SHAPE events (#879, #883)
-* [Linux] Remap Unix keyboard when user changes layout (#895, #897)
-* [Linux] Fix undefined behavior in ewmhSupported() (#892, #901)
-
-
-Graphics
-========
-
-Bugfixes
---------
-* Added support for GL_EXT_texture_edge_clamp for systems that don't expose GL_SGIS_texture_edge_clamp (#880, #882)
-
-
-Audio
-=====
-
-Bugfixes
---------
-* [Android] Fixed audio files not loading (and possibly crashing) (#855, #887)
-
-
-
-SFML 2.3
-========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3
-
-General
-=======
-
-* Examples only link against sfml-main in release mode (#610, #766)
-* Replaced unsigned int with std::size_t for array indices and sizes (#739)
-* Fixed some issues with the Doxygen documentation (#750)
-* Added support for EditorConfig (#751)
-* Hide success message for CMake in quiet mode (#753)
-* Improved documentation for statuses with sf::Ftp (#763)
-* Moved stb_image into the extlibs directory (#795)
-* Changed the SOVERSION to major.minor (#812)
-* Fixed warnings about switch-statements (#863)
-* Added missing includes in the general headers (#851)
-* [Android] Updated toolchain file and dependencies (#791)
-* [Linux] Fixed missing pthread dependency (#794)
-* [OS X] Relaxed CMake installation rules regarding framework dependencies (#767)
-
-Deprecated API
-==============
-
-* sf::Event::MouseWheelEvent: This event is deprecated and potentially inaccurate. Use MouseWheelScrollEvent instead.
-
-Window
-======
-
-Features
---------
-* Added new events for handling high-precision scrolling (#95, #810, #837)
-* Switched from Xlib to XCB (#200, #319, #694, #780, #813, #825)
-* Added support for OpenGL 3 core context creation (#654, #779)
-
-Bugfixes
---------
-* Fixed glXSwapIntervalSGI being broken for some driver implementations (#727, #779)
-* Fixed simultaneous context operations causing crashes on some AMD hardware (#778, #779)
-* Fixed joystick identification (#809, #811)
-* [iOS] Fixed various issues including stencil bits, device orientation and retina support (#748)
-* [iOS] Fixed inconsistency between sf::Touch::getPosition and touch events (#875)
-* [Linux] Fixed Alt+F4 not getting triggered in window mode (#274)
-* [Linux] Fixed Unix joystick stuff (#838)
-* [OS X] Fixed typo in JoystickImpl.cpp to prevent a crash (#762, #765)
-* [OS X] Fixed an issue in InputImpl::getSFOpenGLViewFromSFMLWindow (#782, #792)
-
-Graphics
-========
-
-Features
---------
-* Replaced GLEW with loader generated by glLoadGen (#779)
-* Added a new constructor to sf::Color that takes an sf::Uint32 (#722)
-* Updated stb_image to v2.02 (#777)
-* Updated FreeType to v2.5.5 (#799, #804)
-* Added checks for software OpenGL (#870)
-
-Bugfixes
---------
-* Fixed GL_ARB_compatibility not being detected (#859)
-* Fixed pixel format selection (#862)
-* Bumped back the OpenGL version requirement to 1.1 (#858)
-
-Audio
-=====
-
-Features
---------
-* Dropped libsndfile and started using Vorbis, FLAC and OGG directly (#604, #757)
-* Added a FLAC file to the sound example (#815)
-
-Bugfixes
---------
-* Fixed access violation error in the destructor of sf::AudioDevice (#30, #602)
-* [OS X] Fixed threading issue with sf::SoundStream and OpenAL (#541, #831)
-
-Network
-=======
-
-Bugfixes
---------
-* Fixed sf::TcpSocket not handling partial sends properly (#749, #796)
-
-
-
-SFML 2.2
-========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.2
-
-General
-=======
-
-* Support for iOS and Android platform (#410, #440)
-* Various documentation corrections (#438, #496, #497, #714)
-* Fixed support for compilers on Debian FreeBSD (#380, #578)
-* Added support for Visual Studio 2013 and proper support for the TDM builds (#482)
-* Fixed CMake problems related to FindSFML and cached variables (#637, #684)
-* Switched and enforced LF line endings (#708, #712)
-* Updated OpenAL to version 1.15.1 (d077210)
-* Made compiler and OS variable names much clearer in CMake files (9b0ed30)
-* Re-enabled RPATH feature (e157e7a)
-* Slight adjustments to the examples (#737)
-* [FreeBSD] Various configuration fixes (#577, #578)
-* [Linux] Updated FindSFML.cmake to add UDev to SFML's dependencies (#728, #729, #734, #736)
-* [OS X] Fixed incorrect symlink in freetype.framework (#519)
-* [OS X] CMake module for correct dependencies (#548)
-* [OS X] Fixed SFML target for Xcode (#595, #596)
-* [OS X] Updated implementation, mainly reverting to non-ARC (#601)
-* [OS X] Fixed memory leaks and dead store (#615)
-* [OS X] Improved event handling and performance (#617)
-* [OS X] Reduced memory usage (#672, #698)
-* [OS X] OS X 10.10 support (#691, #699)
-* [OS X] Improve flexibility of dependencies' locations (#713)
-* [Windows] Removed the hack that copied external libraries into SFML static libraries (dbf01a7)
-
-
-System
-======
-
-Features
---------
-* Added substring and replace functions to sf::String (#21, #355)
-* Added toUtfX to sf::String (#501)
-* Added fromUtfX functions to set the internal data to a string by converting from another string in a fixed encoding (#196)
-* Added modulo operator for sf::Time (#429, #430)
-* Added division operator for sf::Time (#453)
-
-Bugfixes
---------
-* Ensured a high resolution for sf::sleep (#439, #475)
-* [Windows] Fixed stack unalignment by two internal functions (#412)
-
-
-Window
-======
-
-Features
---------
-* Added window methods to request and to check focus (#518, #525, #613, #723, #735)
-* Provide name, manufacturer ID and product ID via sf::Joystick (#152, #528)
-* [FreeBSD] Joystick support (#477)
-* [OS X] Improved integration with menus and dock actions (#11)
-* [OS X] Support for OpenGL 3.2 (#84)
-* [OS X] Improved fullscreen support (#343)
-* [OS X] Added support for retina displays (#353, #388)
-* [Windows] Removed support for Windows 9x (#469)
-* [Windows] Fixed typo in Windows keyboard implementation (#516)
-
-Bugfixes
---------
-* sf::Window::create() now also resets framerate limit (#371)
-* Fixed OpenGL context leak (#635, #705)
-* Fixed various joystick problems (memory leak, accelerometer detected, code refactoring) (#660, #686, #742, #743)
-* Optimized sf::Window::waitEvent a bit, no sleep if events are available at first try (ff555d6)
-* [Linux] Output error message when XOpenDisplay() fails (#508, #616)
-* [Linux] Resize window with setSize when sf::Style::Resize is set (#466)
-* [Linux] Fixed broken key repeat on window recreation (#564, #567)
-* [OS X] Fixed KeyReleased not being fired in fullscreen mode (#465)
-* [OS X] Fixed an issue where disconnecting the keyboard would cause a crash (#467)
-* [OS X] Fixed unexpected resizing behavior (#468)
-* [OS X] Improved resizing windows (#474)
-* [OS X] Fixed memory leak with sf::Window::create() (#484)
-* [OS X] Fixed menu shortcuts in fullscreen on OS X (#527)
-* [OS X] Improved cursor hiding (#703)
-* [OS X] Fixed right click not detected with trackpads (#716, #730)
-* [Windows] Fixed joystick POV values (ef1d29b)
-* [Windows] Fixed Unicode inconsistency (#635)
-* [Windows] Fixed Alt+F4 and mouse clicks issues (#437, #457)
-* [Windows] Send MouseButtonReleased event when the mouse is outside of the window (#455, #457)
-* [Windows] Fixed sf::Joystick wrong registry usage (#701, #702, #706)
-
-
-Graphics
-========
-
-Features
---------
-* Provide more information about the loaded font in sf::Font (#164)
-* Implemented a more flexible blending system (#298)
-* Added strikethrough text style (#243, #362, #682)
-* Slight optimization for sf::Text::setString (#413)
-* Added subtraction operator for sf::Color (#114, #145)
-* Optimized sf::Image::flipVertically/flipHorizontally (#555)
-* Changed sf::Font measurements from int to float to allow better underline drawing (#693)
-
-Bugfixes
---------
-* Improved text quality for small and pixelated fonts (#228)
-* Yet another fix for Intel GPUs with sf::RenderTexture (#418)
-* Removed VTab since it causes issues and doesn't have a use nowadays (#442, #445, #460, #588)
-* Fixed broken BDF and PCF font formats (#448)
-* Fixed compilation issue with newer versions of GCC for sf::Rect (#458)
-* Fixed resetGLStates() not explicitly setting the default polygon mode (#480)
-* Fixed division-by-zero in sf::RectangleShape (#499)
-* Fixed potential memory leak in sf::Font (#509)
-* Updated glext and removed glxext (#511, #583)
-* Make sure texture unit 0 is active when resetting sf::RenderTarget states (#523, #591)
-* Fixed texture rect computation in fonts (#669)
-* Improved rendering of underlined text (#593)
-* Avoided repeated output of error messages (#566)
-* Fixed text rendered with vertical offset on ascent and font size mismatch (#576)
-* Fixed rounding problem for viewports (#598)
-* Fixed sf::Shader::isAvailable() possibly breaking context management (#211, #603, #608, #603)
-* Fixed sf::Texture::getMaximumSize() possibly breaking context management (#666)
-* Fixed various sf::Text rendering issues (#692, #699)
-* The texture matrix is now reset in sf::Texture::bind(NULL) (7c4b058)
-* [Windows] Fixed DPI scaling causing strange window behavior (#679, #681, #688)
-
-
-Audio
-=====
-
-Features
---------
-* Added support for selecting the audio capture device (#220, #470)
-* Make sf::SoundRecorder processing frequency configurable (#333)
-* Added up vector to sf::Listener (#545)
-
-Bugfixes
---------
-* Prevented sf::SoundStream::setPlayingOffset() from restarting playing even when paused (#203, #592)
-* Fixed sf::SoundBuffer contents not being able to be updated when still attached to sounds (#354, 367, #390, #589)
-* Catch audio format error and prevent division by zero (#529)
-* Fixed sf::SoundBuffer returning wrong duration for sounds containing more than ~4.3 million samples (2ff58ed)
-* Optimized sf::Listener with a cache (d97e524)
-
-Network
-=======
-
-Features
---------
-* Added support for PUT and DELETE in sf::Http (#257, #312, #607)
-* Added support for chunked HTTP transfers (#296, #337)
-* Added support for 64-bit integers in sf::Packet (#710)
-* Made sf::Ftp::sendCommand() public (2c5cab5)
-
-Bugfixes
---------
-* Checked socket descriptor limit (#153, #628, #683)
-* Fixed sf::TcpSocket::connect()'s switching from blocking to non-blocking mode on immediate connection success (#221)
-* Fixed FTP download and upload file sizes being limited by available RAM (#565, #590)
-* Fixed C++11 compiler warnings for sf::Uint8 (#731, #732)
-
-
-
-SFML 2.1
-========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.1
-
-General
-=======
-
-* Updated the Window and OpenGL examples (got rid of GLU and immediate mode)
-
-Window
-======
-
-Features
---------
-* Now using inotify on Linux to avoid constantly polling joystick connections (#96)
-* Add keypad return, equal and period keys support for OS X
-* Improved mouse events on OS X regarding fullscreen mode
-* Improved mouse events on OS X (#213, #277)
-* Improved reactivity of setMousePosition on OS X (#290)
-* Added support for right control key on OS X
-* Improved TextEntered for OS X (#377)
-* Improved the performances of Window::getSize() (the size is now cached)
-* Added the WM_CLASS property to SFML windows on Linux
-* Fake resize events are no longer sent when the window is moved, on Linux
-* Pressing ALT or F10 on Windows no longer steals the focus
-
-Bugfixes
---------
-* Fixed MouseMove event sometimes not generated when holding left button on Windows (#225)
-* Fixed ContextSettings ignored when creating a 3.x/4.x OpenGL context on Linux (#258)
-* Fixed ContextSettings ignored on Linux when creating a window (#35)
-* Fixed windows bigger than the desktop not appearing on Windows (#215)
-* Fixed KeyRelease events sometimes not reported on Linux (#404)
-* Fixed mouse moved event on OS X when dragging the cursor (#277)
-* Fixed KeyRelease event with CMD key pressed (#381)
-* Fixed taskbar bugs on Windows (#328, #69)
-* Fixed Window::getPosition() on Linux (#346)
-* Unicode characters outside the BMP (> 0xFFFF) are now correctly handled on Windows (#366)
-
-Graphics
-========
-
-Features
---------
-* Checking errors in RenderTarget::pushGLStates() to avoid generating false error messages when user leaves unchecked OpenGL errors (#340)
-* Optimized Shader::setParameter functions, by using a cache internally (#316, #358)
-
-Bugfixes
---------
-* Fixed bounding rect of sf::Text ignoring whitespaces (#216)
-* Solved graphics resources not updated or corrupted when loaded in a thread (#411)
-* Fixed white pixel showing on first character of sf::Text (#414)
-* sf::Rect::contains and sf::Rect::intersects now handle rectangles with negative dimensions correctly (#219)
-* Fixed Shape::setTextureRect not working when called before setTexture
-
-Audio
-=====
-
-Features
---------
-* loadFromStream functions now explicitly reset the stream (seek(0)) before starting to read (#349)
-
-Bugfixes
---------
-* Added a workaround for a bug in the OS X implementation of OpenAL (unsupported channel count no properly detected) (#201)
-* Fixed SoundBuffer::loadFromStream reading past the end of the stream (#214)
-
-Network
-=======
-
-Features
---------
-* Replaced the deprecated gethostbyname with getaddrinfo (#47)
-* Minor improvements to sf::Packet operators (now using strlen and wcslen instead of explicit loops) (#118)
-
-Bugfixes
---------
-* Fixed non-blocking connection with a sf::TcpSocket on Windows
-* Fixed TCP packet data corruption in non-blocking mode (#402, #119)
-* On Unix systems, a socket disconnection no longer stops the program with signal SIGPIPE (#72)
-
-
-
-SFML 2.0
-========
-
-Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.0
-
-No changelog available. Everything changed.
-
-
-
-Older Releases
-==============
-
-See the website for changelogs of older releases: http://www.sfml-dev.org/changelog.php
diff --git a/cmake/Config.cmake b/cmake/Config.cmake
index cff54d0..82a094c 100644
--- a/cmake/Config.cmake
+++ b/cmake/Config.cmake
@@ -31,18 +31,14 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "^k?FreeBSD$")
set(SFML_OS_FREEBSD 1)
# don't use the OpenGL ES implementation on FreeBSD
set(OPENGL_ES 0)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^OpenBSD$")
+ set(SFML_OS_OPENBSD 1)
+ # don't use the OpenGL ES implementation on OpenBSD
+ set(OPENGL_ES 0)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
if(IOS)
set(SFML_OS_IOS 1)
- # set the target framework and platforms
- set(CMAKE_OSX_SYSROOT "iphoneos")
- set(CMAKE_OSX_ARCHITECTURES "armv6;armv7;i386")
- set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator")
-
- # help the compiler detection script below
- set(CMAKE_COMPILER_IS_GNUCXX 1)
-
# use the OpenGL ES implementation on iOS
set(OPENGL_ES 1)
else()
@@ -73,10 +69,23 @@ else()
return()
endif()
+# check if OS or package system supports pkg-config
+# this could be e.g. macports on mac or msys2 on windows etc.
+find_package(PkgConfig QUIET)
+if(PKG_CONFIG_EXECUTABLE)
+ if(EXISTS "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig")
+ set(SFML_OS_SUPPORTS_PKGCONFIG ON)
+ set(SFML_OS_PKGCONFIG_DIR "/lib${LIB_SUFFIX}/pkgconfig")
+ elseif(EXISTS "${CMAKE_INSTALL_PREFIX}/libdata/pkgconfig")
+ set(SFML_OS_SUPPORTS_PKGCONFIG ON)
+ set(SFML_OS_PKGCONFIG_DIR "/libdata/pkgconfig")
+ endif()
+endif()
+
# detect the compiler and its version
# Note: on some platforms (OS X), CMAKE_COMPILER_IS_GNUCXX is true
# even when CLANG is used, therefore the Clang test is done first
-if(CMAKE_CXX_COMPILER MATCHES ".*clang[+][+]" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_CXX_COMPILER MATCHES "clang[+][+]" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# CMAKE_CXX_COMPILER_ID is an internal CMake variable subject to change,
# but there is no other way to detect CLang at the moment
set(SFML_COMPILER_CLANG 1)
@@ -112,12 +121,3 @@ else()
message(FATAL_ERROR "Unsupported compiler")
return()
endif()
-
-# define the install directory for miscellaneous files
-if(SFML_OS_WINDOWS OR SFML_OS_IOS)
- set(INSTALL_MISC_DIR .)
-elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
- set(INSTALL_MISC_DIR share/SFML)
-elseif(SFML_OS_ANDROID)
- set(INSTALL_MISC_DIR ${ANDROID_NDK}/sources/sfml)
-endif()
diff --git a/cmake/Macros.cmake b/cmake/Macros.cmake
index cd2ca8f..be52345 100644
--- a/cmake/Macros.cmake
+++ b/cmake/Macros.cmake
@@ -1,17 +1,45 @@
include(CMakeParseArguments)
+# set the appropriate standard library on each platform for the given target
+# ex: sfml_set_stdlib(sfml-system)
+function(sfml_set_stdlib target)
+ # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled
+ if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4")
+ if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM)
+ target_link_libraries(${target} PRIVATE "-static-libgcc" "-static-libstdc++")
+ elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM)
+ target_link_libraries(${target} PRIVATE "-shared-libgcc" "-shared-libstdc++")
+ endif()
+ endif()
+
+ if (SFML_OS_MACOSX)
+ if (${CMAKE_GENERATOR} MATCHES "Xcode")
+ set_property(TARGET ${target} PROPERTY XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
+ else()
+ target_compile_options(${target} PRIVATE "-stdlib=libc++")
+ target_link_libraries(${target} PRIVATE "-stdlib=libc++")
+ endif()
+ endif()
+endfunction()
+
# add a new target which is a SFML library
# ex: sfml_add_library(sfml-graphics
# SOURCES sprite.cpp image.cpp ...
-# DEPENDS sfml-window sfml-system
-# EXTERNAL_LIBS opengl freetype ...)
+# [STATIC]) # Always create a static library and ignore BUILD_SHARED_LIBS
macro(sfml_add_library target)
# parse the arguments
- cmake_parse_arguments(THIS "" "" "SOURCES;DEPENDS;EXTERNAL_LIBS" ${ARGN})
+ cmake_parse_arguments(THIS "STATIC" "" "SOURCES" ${ARGN})
+ if (NOT "${THIS_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Extra unparsed arguments when calling sfml_add_library: ${THIS_UNPARSED_ARGUMENTS}")
+ endif()
# create the target
- add_library(${target} ${THIS_SOURCES})
+ if (THIS_STATIC)
+ add_library(${target} STATIC ${THIS_SOURCES})
+ else()
+ add_library(${target} ${THIS_SOURCES})
+ endif()
# define the export symbol of the module
string(REPLACE "-" "_" NAME_UPPER "${target}")
@@ -19,7 +47,7 @@ macro(sfml_add_library target)
set_target_properties(${target} PROPERTIES DEFINE_SYMBOL ${NAME_UPPER}_EXPORTS)
# adjust the output file prefix/suffix to match our conventions
- if(BUILD_SHARED_LIBS)
+ if(BUILD_SHARED_LIBS AND NOT THIS_STATIC)
if(SFML_OS_WINDOWS)
# include the major version number in Windows shared library names (but not import library names)
set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d)
@@ -50,14 +78,8 @@ macro(sfml_add_library target)
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(${target} PROPERTIES FOLDER "SFML")
- # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled
- if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4")
- if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM)
- set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++")
- elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM)
- set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++")
- endif()
- endif()
+ # set the target flags to use the appropriate C++ standard library
+ sfml_set_stdlib(${target})
# For Visual Studio on Windows, export debug symbols (PDB files) to lib directory
if(SFML_GENERATE_PDB)
@@ -68,7 +90,7 @@ macro(sfml_add_library target)
set(SFML_PDB_POSTFIX "")
endif()
- if(BUILD_SHARED_LIBS)
+ if(BUILD_SHARED_LIBS AND NOT THIS_STATIC)
# DLLs export debug symbols in the linker PDB (the compiler PDB is an intermediate file)
set_target_properties(${target} PROPERTIES
PDB_NAME "${target}${SFML_PDB_POSTFIX}"
@@ -87,13 +109,8 @@ macro(sfml_add_library target)
set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fvisibility=hidden)
endif()
- # link the target to its SFML dependencies
- if(THIS_DEPENDS)
- target_link_libraries(${target} ${THIS_DEPENDS})
- endif()
-
# build frameworks or dylibs
- if(SFML_OS_MACOSX AND BUILD_SHARED_LIBS)
+ if(SFML_OS_MACOSX AND BUILD_SHARED_LIBS AND NOT THIS_STATIC)
if(SFML_BUILD_FRAMEWORKS)
# adapt target to build frameworks instead of dylibs
set_target_properties(${target} PROPERTIES
@@ -105,9 +122,17 @@ macro(sfml_add_library target)
endif()
# adapt install directory to allow distributing dylibs/frameworks in user's frameworks/application bundle
- set_target_properties(${target} PROPERTIES
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@rpath")
+ # but only if cmake rpath options aren't set
+ if(NOT CMAKE_SKIP_RPATH AND NOT CMAKE_SKIP_INSTALL_RPATH AND NOT CMAKE_INSTALL_RPATH AND NOT CMAKE_INSTALL_RPATH_USE_LINK_PATH AND NOT CMAKE_INSTALL_NAME_DIR)
+ set_target_properties(${target} PROPERTIES INSTALL_NAME_DIR "@rpath")
+ if(NOT CMAKE_SKIP_BUILD_RPATH)
+ if (CMAKE_VERSION VERSION_LESS 3.9)
+ set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
+ else()
+ set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_NAME_DIR TRUE)
+ endif()
+ endif()
+ endif()
endif()
# enable automatic reference counting on iOS
@@ -127,37 +152,60 @@ macro(sfml_add_library target)
endif()
endif()
- # link the target to its external dependencies
- if(THIS_EXTERNAL_LIBS)
- target_link_libraries(${target} ${THIS_EXTERNAL_LIBS})
- endif()
-
# add the install rule
- install(TARGETS ${target}
+ install(TARGETS ${target} EXPORT SFMLConfigExport
RUNTIME DESTINATION bin COMPONENT bin
LIBRARY DESTINATION lib${LIB_SUFFIX} COMPONENT bin
ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel
- FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX} COMPONENT bin)
+ FRAMEWORK DESTINATION "." COMPONENT bin)
+
+ # add <project>/include as public include directory
+ target_include_directories(${target}
+ PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+ PRIVATE ${PROJECT_SOURCE_DIR}/src)
+
+ if (SFML_BUILD_FRAMEWORKS)
+ target_include_directories(${target} INTERFACE $<INSTALL_INTERFACE:SFML.framework>)
+ else()
+ target_include_directories(${target} INTERFACE $<INSTALL_INTERFACE:include>)
+ endif()
+
+ # define SFML_STATIC if the build type is not set to 'shared'
+ if(NOT BUILD_SHARED_LIBS)
+ target_compile_definitions(${target} PUBLIC "SFML_STATIC")
+ endif()
+
endmacro()
# add a new target which is a SFML example
# ex: sfml_add_example(ftp
# SOURCES ftp.cpp ...
-# DEPENDS sfml-network sfml-system)
+# BUNDLE_RESOURCES MainMenu.nib ... # Files to be added in target but not installed next to the executable
+# DEPENDS sfml-network
+# RESOURCES_DIR resources) # A directory to install next to the executable and sources
macro(sfml_add_example target)
# parse the arguments
- cmake_parse_arguments(THIS "GUI_APP" "" "SOURCES;DEPENDS" ${ARGN})
+ cmake_parse_arguments(THIS "GUI_APP" "RESOURCES_DIR" "SOURCES;BUNDLE_RESOURCES;DEPENDS" ${ARGN})
# set a source group for the source files
source_group("" FILES ${THIS_SOURCES})
+ # check whether resources must be added in target
+ set(target_input ${THIS_SOURCES})
+ if(THIS_BUNDLE_RESOURCES)
+ set(target_input ${target_input} ${THIS_BUNDLE_RESOURCES})
+ endif()
+
# create the target
if(THIS_GUI_APP AND SFML_OS_WINDOWS AND NOT DEFINED CMAKE_CONFIGURATION_TYPES AND ${CMAKE_BUILD_TYPE} STREQUAL "Release")
- add_executable(${target} WIN32 ${THIS_SOURCES})
- target_link_libraries(${target} sfml-main)
+ add_executable(${target} WIN32 ${target_input})
+ target_link_libraries(${target} PRIVATE sfml-main)
+ elseif(THIS_GUI_APP AND SFML_OS_IOS)
+ add_executable(${target} MACOSX_BUNDLE ${target_input})
+ target_link_libraries(${target} PRIVATE sfml-main)
else()
- add_executable(${target} ${THIS_SOURCES})
+ add_executable(${target} ${target_input})
endif()
# set the debug suffix
@@ -166,61 +214,128 @@ macro(sfml_add_example target)
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(${target} PROPERTIES FOLDER "Examples")
- # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled
- if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4")
- if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM)
- set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++")
- elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM)
- set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++")
- endif()
- endif()
+ # set the target flags to use the appropriate C++ standard library
+ sfml_set_stdlib(${target})
+
+ # set the Visual Studio startup path for debugging
+ set_target_properties(${target} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# link the target to its SFML dependencies
if(THIS_DEPENDS)
- target_link_libraries(${target} ${THIS_DEPENDS})
+ target_link_libraries(${target} PRIVATE ${THIS_DEPENDS})
endif()
# add the install rule
install(TARGETS ${target}
- RUNTIME DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples
- BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples)
+ RUNTIME DESTINATION ${SFML_MISC_INSTALL_PREFIX}/examples/${target} COMPONENT examples
+ BUNDLE DESTINATION ${SFML_MISC_INSTALL_PREFIX}/examples/${target} COMPONENT examples)
# install the example's source code
install(FILES ${THIS_SOURCES}
- DESTINATION ${INSTALL_MISC_DIR}/examples/${target}
+ DESTINATION ${SFML_MISC_INSTALL_PREFIX}/examples/${target}
COMPONENT examples)
- # install the example's resources as well
- set(EXAMPLE_RESOURCES "${CMAKE_SOURCE_DIR}/examples/${target}/resources")
- if(EXISTS ${EXAMPLE_RESOURCES})
- install(DIRECTORY ${EXAMPLE_RESOURCES}
- DESTINATION ${INSTALL_MISC_DIR}/examples/${target}
+ if (THIS_RESOURCES_DIR)
+ # install the example's resources as well
+ get_filename_component(THIS_RESOURCES_DIR "${THIS_RESOURCES_DIR}" ABSOLUTE)
+
+ if(NOT EXISTS "${THIS_RESOURCES_DIR}")
+ message(FATAL_ERROR "Given resources directory to install does not exist: ${THIS_RESOURCES_DIR}")
+ endif()
+ install(DIRECTORY ${THIS_RESOURCES_DIR}
+ DESTINATION ${SFML_MISC_INSTALL_PREFIX}/examples/${target}
COMPONENT examples)
endif()
endmacro()
-# macro to find packages on the host OS
-# this is the same as in the toolchain file, which is here for Nsight Tegra VS
-# since it won't use the Android toolchain file
-if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
- macro(find_host_package)
- set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
- set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
- set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
- if(CMAKE_HOST_WIN32)
- set(WIN32 1)
- set(UNIX)
- elseif(CMAKE_HOST_APPLE)
- set(APPLE 1)
- set(UNIX)
- endif()
- find_package(${ARGN})
- set(WIN32)
- set(APPLE)
- set(UNIX 1)
- set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
- set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
- set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
- endmacro()
-endif()
+
+# Find the requested package and make an INTERFACE library from it
+# Usage: sfml_find_package(wanted_target_name
+# [INCLUDE "OPENGL_INCLUDE_DIR"]
+# [LINK "OPENGL_gl_LIBRARY"])
+function(sfml_find_package)
+ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
+ list(GET ARGN 0 target)
+ list(REMOVE_AT ARGN 0)
+
+ if (TARGET ${target})
+ message(FATAL_ERROR "Target '${target}' is already defined")
+ endif()
+
+ cmake_parse_arguments(THIS "" "" "INCLUDE;LINK" ${ARGN})
+ if (THIS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments when calling sfml_import_library: ${THIS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if (SFML_OS_IOS)
+ find_host_package(${target} REQUIRED)
+ else()
+ find_package(${target} REQUIRED)
+ endif()
+
+ add_library(${target} INTERFACE)
+
+ if (THIS_INCLUDE)
+ foreach(include_dir IN LISTS "${THIS_INCLUDE}")
+ if (NOT include_dir)
+ message(FATAL_ERROR "No path given for include dir ${THIS_INCLUDE}")
+ endif()
+ target_include_directories(${target} INTERFACE "$<BUILD_INTERFACE:${include_dir}>")
+ endforeach()
+ endif()
+
+ if (THIS_LINK)
+ foreach(link_item IN LISTS ${THIS_LINK})
+ if (NOT link_item)
+ message(FATAL_ERROR "Missing item in ${THIS_LINK}")
+ endif()
+ target_link_libraries(${target} INTERFACE "$<BUILD_INTERFACE:${link_item}>")
+ endforeach()
+ endif()
+ install(TARGETS ${target} EXPORT SFMLConfigExport)
+endfunction()
+
+# Generate a SFMLConfig.cmake file (and associated files) from the targets registered against
+# the EXPORT name "SFMLConfigExport" (EXPORT parameter of install(TARGETS))
+function(sfml_export_targets)
+ # CMAKE_CURRENT_LIST_DIR or CMAKE_CURRENT_SOURCE_DIR not usable for files that are to be included like this one
+ set(CURRENT_DIR "${PROJECT_SOURCE_DIR}/cmake")
+
+ include(CMakePackageConfigHelpers)
+ write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/SFMLConfigVersion.cmake"
+ VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
+ COMPATIBILITY SameMajorVersion)
+
+ if (BUILD_SHARED_LIBS)
+ set(config_name "Shared")
+ else()
+ set(config_name "Static")
+ endif()
+ set(targets_config_filename "SFML${config_name}Targets.cmake")
+
+ export(EXPORT SFMLConfigExport
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/${targets_config_filename}")
+
+ if (SFML_BUILD_FRAMEWORKS)
+ set(config_package_location "SFML.framework/Resources/CMake")
+ else()
+ set(config_package_location lib/cmake/SFML)
+ endif()
+ configure_package_config_file("${CURRENT_DIR}/SFMLConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfig.cmake"
+ INSTALL_DESTINATION "${config_package_location}")
+ configure_package_config_file("${CURRENT_DIR}/SFMLConfigDependencies.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfigDependencies.cmake"
+ INSTALL_DESTINATION "${config_package_location}")
+
+
+ install(EXPORT SFMLConfigExport
+ FILE ${targets_config_filename}
+ DESTINATION ${config_package_location})
+
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfigDependencies.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfigVersion.cmake"
+ DESTINATION ${config_package_location}
+ COMPONENT devel)
+endfunction()
+
diff --git a/cmake/Modules/FindSFML.cmake b/cmake/Modules/FindSFML.cmake
deleted file mode 100644
index fe84c96..0000000
--- a/cmake/Modules/FindSFML.cmake
+++ /dev/null
@@ -1,365 +0,0 @@
-# This script locates the SFML library
-# ------------------------------------
-#
-# Usage
-# -----
-#
-# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main).
-# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing.
-# example:
-# find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules
-#
-# You can enforce a specific version, either MAJOR.MINOR or only MAJOR.
-# If nothing is specified, the version won't be checked (i.e. any version will be accepted).
-# example:
-# find_package(SFML COMPONENTS ...) # no specific version required
-# find_package(SFML 2 COMPONENTS ...) # any 2.x version
-# find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater
-#
-# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
-# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
-# Since you have to link yourself all the SFML dependencies when you link it statically, the following
-# additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed
-# description below).
-# In case of static linking, the SFML_STATIC macro will also be defined by this script.
-# example:
-# set(SFML_STATIC_LIBRARIES TRUE)
-# find_package(SFML 2 COMPONENTS network system)
-#
-# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless
-# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details.
-# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which
-# are available for both release and debug modes.
-#
-# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable
-# to tell CMake where SFML is.
-#
-# Output
-# ------
-#
-# This script defines the following variables:
-# - For each specified module XXX (system, window, graphics, network, audio, main):
-# - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found)
-# - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found)
-# - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary)
-# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found
-# - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking
-# - SFML_LIBRARIES: the list of all libraries corresponding to the required modules
-# - SFML_FOUND: true if all the required modules are found
-# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file)
-# - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking
-#
-# example:
-# find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED)
-# include_directories(${SFML_INCLUDE_DIR})
-# add_executable(myapp ...)
-# target_link_libraries(myapp ${SFML_LIBRARIES})
-
-# define the SFML_STATIC macro if static build was chosen
-if(SFML_STATIC_LIBRARIES)
- add_definitions(-DSFML_STATIC)
-endif()
-
-# define the list of search paths for headers and libraries
-set(FIND_SFML_PATHS
- ${SFML_ROOT}
- $ENV{SFML_ROOT}
- ~/Library/Frameworks
- /Library/Frameworks
- /usr/local
- /usr
- /sw
- /opt/local
- /opt/csw
- /opt)
-
-# find the SFML include directory
-find_path(SFML_INCLUDE_DIR SFML/Config.hpp
- PATH_SUFFIXES include
- PATHS ${FIND_SFML_PATHS})
-
-# check the version number
-set(SFML_VERSION_OK TRUE)
-if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
- # extract the major and minor version numbers from SFML/Config.hpp
- # we have to handle framework a little bit differently:
- if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework")
- set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp")
- else()
- set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
- endif()
- FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS)
- STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}")
- STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}")
- STRING(REGEX REPLACE ".*#define SFML_VERSION_PATCH ([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}")
- if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$")
- set(SFML_VERSION_PATCH 0)
- endif()
- math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}")
-
- # if we could extract them, compare with the requested version number
- if (SFML_VERSION_MAJOR)
- # transform version numbers to an integer
- math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10000 + ${SFML_VERSION_MINOR} * 100 + ${SFML_VERSION_PATCH}")
-
- # compare them
- if(SFML_VERSION LESS SFML_REQUESTED_VERSION)
- set(SFML_VERSION_OK FALSE)
- endif()
- else()
- # SFML version is < 2.0
- if (SFML_REQUESTED_VERSION GREATER 10900)
- set(SFML_VERSION_OK FALSE)
- set(SFML_VERSION_MAJOR 1)
- set(SFML_VERSION_MINOR x)
- set(SFML_VERSION_PATCH x)
- endif()
- endif()
-endif()
-
-# find the requested modules
-set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found
-foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS})
- string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER)
- string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER)
- set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER})
-
- # no suffix for sfml-main, it is always a static library
- if(FIND_SFML_COMPONENT_LOWER STREQUAL "main")
- # release library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
- NAMES ${FIND_SFML_COMPONENT_NAME}
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
-
- # debug library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
- NAMES ${FIND_SFML_COMPONENT_NAME}-d
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
- else()
- # static release library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
- NAMES ${FIND_SFML_COMPONENT_NAME}-s
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
-
- # static debug library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
- NAMES ${FIND_SFML_COMPONENT_NAME}-s-d
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
-
- # dynamic release library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
- NAMES ${FIND_SFML_COMPONENT_NAME}
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
-
- # dynamic debug library
- find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG
- NAMES ${FIND_SFML_COMPONENT_NAME}-d
- PATH_SUFFIXES lib64 lib
- PATHS ${FIND_SFML_PATHS})
-
- # choose the entries that fit the requested link type
- if(SFML_STATIC_LIBRARIES)
- if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE})
- endif()
- if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG})
- endif()
- else()
- if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE})
- endif()
- if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG})
- endif()
- endif()
- endif()
-
- if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
- # library found
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE)
-
- # if both are found, set SFML_XXX_LIBRARY to contain both
- if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}
- optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
- endif()
-
- # if only one debug/release variant is found, set the other to be equal to the found one
- if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
- # debug and not release
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
- endif()
- if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG)
- # release and not debug
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
- endif()
- else()
- # library not found
- set(SFML_FOUND FALSE)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE)
- set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "")
- set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY")
- endif()
-
- # mark as advanced
- MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
- SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
-
- # add to the global list of libraries
- set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}")
-endforeach()
-
-# in case of static linking, we must also define the list of all the dependencies of SFML libraries
-if(SFML_STATIC_LIBRARIES)
-
- # detect the OS
- if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
- set(FIND_SFML_OS_WINDOWS 1)
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set(FIND_SFML_OS_LINUX 1)
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- set(FIND_SFML_OS_FREEBSD 1)
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(FIND_SFML_OS_MACOSX 1)
- endif()
-
- # start with an empty list
- set(SFML_DEPENDENCIES)
- set(FIND_SFML_DEPENDENCIES_NOTFOUND)
-
- # macro that searches for a 3rd-party library
- macro(find_sfml_dependency output friendlyname)
- # No lookup in environment variables (PATH on Windows), as they may contain wrong library versions
- find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH)
- if(${${output}} STREQUAL "${output}-NOTFOUND")
- unset(output)
- set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}")
- endif()
- endmacro()
-
- # sfml-system
- list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT)
- if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1)
-
- # update the list -- these are only system libraries, no need to find them
- if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX)
- set(SFML_SYSTEM_DEPENDENCIES "pthread")
- endif()
- if(FIND_SFML_OS_LINUX)
- set(SFML_SYSTEM_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} "rt")
- endif()
- if(FIND_SFML_OS_WINDOWS)
- set(SFML_SYSTEM_DEPENDENCIES "winmm")
- endif()
- set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES})
- endif()
-
- # sfml-network
- list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT)
- if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1)
-
- # update the list -- these are only system libraries, no need to find them
- if(FIND_SFML_OS_WINDOWS)
- set(SFML_NETWORK_DEPENDENCIES "ws2_32")
- endif()
- set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES})
- endif()
-
- # sfml-window
- list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT)
- if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1)
-
- # find libraries
- if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
- find_sfml_dependency(X11_LIBRARY "X11" X11)
- find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr)
- endif()
-
- if(FIND_SFML_OS_LINUX)
- find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev)
- endif()
-
- # update the list
- if(FIND_SFML_OS_WINDOWS)
- set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32")
- elseif(FIND_SFML_OS_LINUX)
- set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} ${UDEV_LIBRARIES})
- elseif(FIND_SFML_OS_FREEBSD)
- set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} "usbhid")
- elseif(FIND_SFML_OS_MACOSX)
- set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon")
- endif()
- set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES})
- endif()
-
- # sfml-graphics
- list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT)
- if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1)
-
- # find libraries
- find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype)
- find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg)
-
- # update the list
- set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
- set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES})
- endif()
-
- # sfml-audio
- list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT)
- if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1)
-
- # find libraries
- find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32)
- find_sfml_dependency(OGG_LIBRARY "Ogg" ogg)
- find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis)
- find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile)
- find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc)
- find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC)
-
- # update the list
- set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
- set(SFML_DEPENDENCIES ${SFML_DEPENDENCIES} ${SFML_AUDIO_DEPENDENCIES})
- endif()
-
-endif()
-
-# handle errors
-if(NOT SFML_VERSION_OK)
- # SFML version not ok
- set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH})")
- set(SFML_FOUND FALSE)
-elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND)
- set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})")
- set(SFML_FOUND FALSE)
-elseif(NOT SFML_FOUND)
- # include directory or library not found
- set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})")
-endif()
-if (NOT SFML_FOUND)
- if(SFML_FIND_REQUIRED)
- # fatal error
- message(FATAL_ERROR ${FIND_SFML_ERROR})
- elseif(NOT SFML_FIND_QUIETLY)
- # error but continue
- message("${FIND_SFML_ERROR}")
- endif()
-endif()
-
-# handle success
-if(SFML_FOUND AND NOT SFML_FIND_QUIETLY)
- message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH} in ${SFML_INCLUDE_DIR}")
-endif()
diff --git a/cmake/Modules/FindUDev.cmake b/cmake/Modules/FindUDev.cmake
index 9ae3cf8..467bd69 100644
--- a/cmake/Modules/FindUDev.cmake
+++ b/cmake/Modules/FindUDev.cmake
@@ -50,3 +50,4 @@ ELSE (UDEV_FOUND)
ENDIF (UDev_FIND_REQUIRED)
ENDIF (UDEV_FOUND)
+mark_as_advanced(UDEV_INCLUDE_DIR UDEV_LIBRARIES)
diff --git a/cmake/Modules/FindVorbis.cmake b/cmake/Modules/FindVorbis.cmake
index 645bba7..e285411 100644
--- a/cmake/Modules/FindVorbis.cmake
+++ b/cmake/Modules/FindVorbis.cmake
@@ -12,13 +12,18 @@ find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
find_library(OGG_LIBRARY NAMES ogg)
find_library(VORBIS_LIBRARY NAMES vorbis)
-find_library(VORBISFILE_LIBRARY NAMES vorbisfile)
-find_library(VORBISENC_LIBRARY NAMES vorbisenc)
+if (NOT SFML_OS_IOS)
+ find_library(VORBISFILE_LIBRARY NAMES vorbisfile)
+ find_library(VORBISENC_LIBRARY NAMES vorbisenc)
+ set(VORBIS_LIBRARIES ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
+else()
+ set(VORBIS_LIBRARIES ${VORBIS_LIBRARY} ${OGG_LIBRARY})
+endif()
include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(VORBIS DEFAULT_MSG VORBIS_LIBRARY VORBISFILE_LIBRARY VORBISENC_LIBRARY OGG_LIBRARY VORBIS_INCLUDE_DIR OGG_INCLUDE_DIR)
+
+find_package_handle_standard_args(VORBIS DEFAULT_MSG VORBIS_LIBRARIES VORBIS_INCLUDE_DIR OGG_INCLUDE_DIR)
set(VORBIS_INCLUDE_DIRS ${OGG_INCLUDE_DIR} ${VORBIS_INCLUDE_DIR})
-set(VORBIS_LIBRARIES ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
mark_as_advanced(OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY VORBISENC_LIBRARY)
diff --git a/cmake/SFMLConfig.cmake.in b/cmake/SFMLConfig.cmake.in
new file mode 100644
index 0000000..ce81953
--- /dev/null
+++ b/cmake/SFMLConfig.cmake.in
@@ -0,0 +1,148 @@
+# This script provides the SFML libraries as imported targets
+# ------------------------------------
+#
+# Usage
+# -----
+#
+# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main).
+# If none is given, no imported target will be created and you won't be able to link to SFML libraries.
+# example:
+# find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules
+#
+# You can enforce a specific version, either MAJOR.MINOR or only MAJOR.
+# If nothing is specified, the version won't be checked (i.e. any version will be accepted).
+# example:
+# find_package(SFML COMPONENTS ...) # no specific version required
+# find_package(SFML 2 COMPONENTS ...) # any 2.x version
+# find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater
+#
+# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
+# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
+# You don't need to deal with SFML's dependencies when linking your targets against SFML libraries,
+# they will all be configured automatically, even if you use SFML static libraries.
+# example:
+# set(SFML_STATIC_LIBRARIES TRUE)
+# find_package(SFML 2 COMPONENTS network system)
+#
+# On macOS by default CMake will search for frameworks. If you want to use static libraries and have installed
+# both SFML frameworks and SFML static libraries, your must set CMAKE_FIND_FRAMEWORK to "NEVER" or "LAST"
+# in addition to setting SFML_STATIC_LIBRARIES to TRUE. Otherwise CMake will check the frameworks bundle config and
+# fail after finding out that it does not provide static libraries. Please refer to CMake documentation for more details.
+#
+# Additionally, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which
+# are available for both release and debug modes.
+#
+# If SFML is not installed in a standard path, you can use the SFML_DIR CMake variable
+# to tell CMake where SFML's config file is located (PREFIX/lib/cmake/SFML for a library-based installation,
+# and PREFIX/SFML.framework/Resources/CMake on macOS for a framework-based installation).
+#
+# Output
+# ------
+#
+# This script defines the following variables:
+# - For each specified module XXX (system, window, graphics, network, audio, main):
+# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found
+# - SFML_FOUND: true if all the required modules are found
+#
+# And the following targets:
+# - For each specified module XXX (system, window, graphics, network, audio, main):
+# - sfml-XXX
+# The SFML targets are the same for both Debug and Release build configurations and will automatically provide
+# correct settings based on your currently active build configuration. The SFML targets name also do not change
+# when using dynamic or static SFML libraries.
+#
+# When linking against a SFML target, you do not need to specify indirect dependencies. For example, linking
+# against sfml-graphics will also automatically link against sfml-window and sfml-system.
+#
+# example:
+# find_package(SFML 2 COMPONENTS graphics audio REQUIRED)
+# add_executable(myapp ...)
+# target_link_libraries(myapp sfml-graphics sfml-audio)
+
+if (NOT SFML_FIND_COMPONENTS)
+ message(FATAL_ERROR "find_package(SFML) called with no component")
+endif()
+
+set(FIND_SFML_PATHS
+ "${CMAKE_CURRENT_LIST_DIR}/../.."
+ ${SFML_ROOT}
+ $ENV{SFML_ROOT}
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local
+ /usr
+ /sw
+ /opt/local
+ /opt/csw
+ /opt)
+
+find_path(SFML_DOC_DIR SFML.tag
+ PATH_SUFFIXES SFML/doc share/SFML/doc
+ PATHS ${FIND_SFML_PATHS})
+
+
+# Update requested components (eg. request window component if graphics component was requested)
+set(FIND_SFML_SYSTEM_DEPENDENCIES "")
+set(FIND_SFML_MAIN_DEPENDENCIES "")
+set(FIND_SFML_AUDIO_DEPENDENCIES system)
+set(FIND_SFML_NETWORK_DEPENDENCIES system)
+set(FIND_SFML_WINDOW_DEPENDENCIES system)
+set(FIND_SFML_GRAPHICS_DEPENDENCIES window system)
+set(FIND_SFML_ADDITIONAL_COMPONENTS "")
+foreach(component ${SFML_FIND_COMPONENTS})
+ string(TOUPPER "${component}" UPPER_COMPONENT)
+ list(APPEND FIND_SFML_ADDITIONAL_COMPONENTS ${FIND_SFML_${UPPER_COMPONENT}_DEPENDENCIES})
+endforeach()
+list(APPEND SFML_FIND_COMPONENTS ${FIND_SFML_ADDITIONAL_COMPONENTS})
+list(REMOVE_DUPLICATES SFML_FIND_COMPONENTS)
+
+# Choose which target definitions must be imported
+if (SFML_STATIC_LIBRARIES)
+ set(SFML_IS_FRAMEWORK_INSTALL "@SFML_BUILD_FRAMEWORKS@")
+ if (SFML_IS_FRAMEWORK_INSTALL)
+ message(WARNING "Static frameworks are not supported by SFML. Clear SFML_DIR cache entry, \
+and either change SFML_STATIC_LIBRARIES or CMAKE_FIND_FRAMEWORK before calling find_package(SFML)")
+ endif()
+ set(config_name "Static")
+else()
+ set(config_name "Shared")
+endif()
+set(targets_config_file "${CMAKE_CURRENT_LIST_DIR}/SFML${config_name}Targets.cmake")
+
+# Generate imported targets for SFML and its dependencies
+if (EXISTS "${targets_config_file}")
+ # Set SFML_FOUND to TRUE by default, may be overwritten by one of the includes below
+ set(SFML_FOUND TRUE)
+ include("${targets_config_file}")
+ include("${CMAKE_CURRENT_LIST_DIR}/SFMLConfigDependencies.cmake")
+
+ if (SFML_FOUND)
+ foreach (component ${SFML_FIND_COMPONENTS})
+ string(TOUPPER "${component}" UPPER_COMPONENT)
+ if (TARGET sfml-${component})
+ set(SFML_${UPPER_COMPONENT}_FOUND TRUE)
+ else()
+ set(FIND_SFML_ERROR "Found SFML but requested component '${component}' is missing in the config defined in ${SFML_DIR}.")
+ set(SFML_${UPPER_COMPONENT}_FOUND FALSE)
+ set(SFML_FOUND FALSE)
+ endif()
+ endforeach()
+ endif()
+else()
+ set(FIND_SFML_ERROR "Requested SFML configuration (${config_name}) was not found")
+ set(SFML_FOUND FALSE)
+endif()
+
+if (NOT SFML_FOUND)
+ if(SFML_FIND_REQUIRED)
+ # fatal error
+ message(FATAL_ERROR "${FIND_SFML_ERROR}")
+ elseif(NOT SFML_FIND_QUIETLY)
+ # error but continue
+ message(STATUS "${FIND_SFML_ERROR}")
+ endif()
+endif()
+
+if (SFML_FOUND AND NOT SFML_FIND_QUIETLY)
+ message(STATUS "Found SFML @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@ in ${CMAKE_CURRENT_LIST_DIR}")
+endif()
diff --git a/cmake/SFMLConfigDependencies.cmake.in b/cmake/SFMLConfigDependencies.cmake.in
new file mode 100644
index 0000000..2f85b38
--- /dev/null
+++ b/cmake/SFMLConfigDependencies.cmake.in
@@ -0,0 +1,80 @@
+
+if (CMAKE_VERSION VERSION_LESS 3.5.2)
+ include(CMakeParseArguments)
+endif()
+
+# in case of static linking, we must also define the list of all the dependencies of SFML libraries
+if(SFML_STATIC_LIBRARIES)
+ # detect the OS
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(FIND_SFML_OS_WINDOWS 1)
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(FIND_SFML_OS_LINUX 1)
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+ set(FIND_SFML_OS_FREEBSD 1)
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(FIND_SFML_OS_MACOSX 1)
+ endif()
+
+ # start with an empty list
+ set(FIND_SFML_DEPENDENCIES_NOTFOUND)
+
+ # macro that searches for a 3rd-party library
+ function(sfml_bind_dependency)
+ cmake_parse_arguments(THIS "" "TARGET;FRIENDLY_NAME" "SEARCH_NAMES" ${ARGN})
+ if (THIS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments when calling sfml_bind_dependency: ${THIS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ # No lookup in environment variables (PATH on Windows), as they may contain wrong library versions
+ find_library(${THIS_FRIENDLY_NAME}_LIB NAMES ${THIS_SEARCH_NAMES}
+ PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH)
+ mark_as_advanced(${THIS_FRIENDLY_NAME}_LIB)
+ if(${THIS_FRIENDLY_NAME}_LIB)
+ set_property(TARGET ${THIS_TARGET} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${${THIS_FRIENDLY_NAME}_LIB}")
+ else()
+ set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${THIS_FRIENDLY_NAME}" PARENT_SCOPE)
+ endif()
+ endfunction()
+
+ # sfml-window
+ list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT_INDEX)
+ if(FIND_SFML_WINDOW_COMPONENT_INDEX GREATER -1)
+ if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
+ sfml_bind_dependency(TARGET X11 FRIENDLY_NAME "X11" SEARCH_NAMES "X11")
+ sfml_bind_dependency(TARGET X11 FRIENDLY_NAME "Xrandr" SEARCH_NAMES "Xrandr")
+ endif()
+
+ if(FIND_SFML_OS_LINUX)
+ sfml_bind_dependency(TARGET UDev FRIENDLY_NAME "UDev" SEARCH_NAMES "udev" "libudev")
+ endif()
+
+ if (FIND_SFML_OS_WINDOWS)
+ set_property(TARGET OpenGL APPEND PROPERTY INTERFACE_LINK_LIBRARIES "OpenGL32")
+ else()
+ sfml_bind_dependency(TARGET OpenGL FRIENDLY_NAME "OpenGL" SEARCH_NAMES "OpenGL" "GL")
+ endif()
+ endif()
+
+ # sfml-graphics
+ list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT_INDEX)
+ if(FIND_SFML_GRAPHICS_COMPONENT_INDEX GREATER -1)
+ sfml_bind_dependency(TARGET Freetype FRIENDLY_NAME "FreeType" SEARCH_NAMES "freetype")
+ endif()
+
+ # sfml-audio
+ list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT_INDEX)
+ if(FIND_SFML_AUDIO_COMPONENT_INDEX GREATER -1)
+ sfml_bind_dependency(TARGET OpenAL FRIENDLY_NAME "OpenAL" SEARCH_NAMES "OpenAL" "openal" "openal32")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "Ogg" SEARCH_NAMES "ogg")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "Vorbis" SEARCH_NAMES "vorbis")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisFile" SEARCH_NAMES "vorbisfile")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisEnc" SEARCH_NAMES "vorbisenc")
+ sfml_bind_dependency(TARGET FLAC FRIENDLY_NAME "FLAC" SEARCH_NAMES "FLAC")
+ endif()
+
+ if (FIND_SFML_DEPENDENCIES_NOTFOUND)
+ set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})")
+ set(SFML_FOUND FALSE)
+ endif()
+endif()
diff --git a/cmake/toolchains/android.toolchain.cmake b/cmake/toolchains/android.toolchain.cmake
index d0fdf00..ee28e51 100644
--- a/cmake/toolchains/android.toolchain.cmake
+++ b/cmake/toolchains/android.toolchain.cmake
@@ -810,20 +810,16 @@ else()
endif()
set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
- if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
- set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- endif()
+ list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
+ set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
endif()
unset( __levelIdx )
# remember target ABI
set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
-if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
- set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
-endif()
+list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
+set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
# runtime choice (STL, rtti, exceptions)
@@ -1137,9 +1133,6 @@ if( NOT CMAKE_C_COMPILER )
endif()
set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
-if( CMAKE_VERSION VERSION_LESS 2.8.5 )
- set( CMAKE_ASM_COMPILER_ARG1 "-c" )
-endif()
if( APPLE )
find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
if( NOT CMAKE_INSTALL_NAME_TOOL )
@@ -1443,7 +1436,7 @@ if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
endif()
# pie/pic
-if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
+if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE))
set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
else()
@@ -1555,51 +1548,6 @@ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-
-# macro to find packages on the host OS
-macro( find_host_package )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_package( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
-# macro to find programs on the host OS
-macro( find_host_program )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_program( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
# export toolchain settings for the try_compile() command
if( NOT _CMAKE_IN_TRY_COMPILE )
set( __toolchain_config "")
@@ -1715,4 +1663,4 @@ endif()
# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
# ANDROID_NDK_SEARCH_PATHS
# ANDROID_SUPPORTED_ABIS_${ARCH}
-# ANDROID_SUPPORTED_NDK_VERSIONS \ No newline at end of file
+# ANDROID_SUPPORTED_NDK_VERSIONS
diff --git a/cmake/toolchains/iOS.toolchain.cmake b/cmake/toolchains/iOS.toolchain.cmake
new file mode 100644
index 0000000..abbff03
--- /dev/null
+++ b/cmake/toolchains/iOS.toolchain.cmake
@@ -0,0 +1,217 @@
+# Copyright (c) 2016, Bogdan Cristea <cristeab@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
+# files which are included with CMake 2.8.4
+# It has been altered for iOS development
+
+# Options:
+#
+# IOS_PLATFORM = OS (default) or SIMULATOR
+# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
+# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
+# SIMULATOR - used to build for the Simulator platforms, which have an x86_64 arch.
+#
+# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
+# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
+# If set manually, it will override the default location and force the user of a particular Developer Platform
+#
+# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
+# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
+# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
+# If set manually, this will force the use of a specific SDK version
+
+# Macros:
+#
+# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE)
+# A convenience macro for setting xcode specific properties on targets
+# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1")
+#
+# find_host_package (PROGRAM ARGS)
+# A macro used to find executable programs on the host system, not within the iOS environment.
+# Thanks to the android-cmake project for providing the command
+
+# Standard settings
+set (CMAKE_SYSTEM_NAME Darwin)
+set (CMAKE_SYSTEM_VERSION 1)
+set (UNIX True)
+set (APPLE True)
+set (IOS True)
+
+# Required as of cmake 2.8.10
+set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
+
+# Determine the cmake host system version so we know where to find the iOS SDKs
+find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)
+if (CMAKE_UNAME)
+ exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
+ string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
+endif (CMAKE_UNAME)
+
+set(CMAKE_C_COMPILER /usr/bin/gcc CACHE FILEPATH "" FORCE)
+set(CMAKE_CXX_COMPILER /usr/bin/g++ CACHE FILEPATH "" FORCE)
+set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
+
+# Skip the platform compiler checks for cross compiling
+set (CMAKE_CXX_COMPILER_WORKS TRUE)
+set (CMAKE_C_COMPILER_WORKS TRUE)
+
+# All iOS/Darwin specific settings - some may be redundant
+set (CMAKE_SHARED_LIBRARY_PREFIX "lib")
+set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
+set (CMAKE_SHARED_MODULE_PREFIX "lib")
+set (CMAKE_SHARED_MODULE_SUFFIX ".so")
+set (CMAKE_MODULE_EXISTS 1)
+set (CMAKE_DL_LIBS "")
+
+set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
+set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
+set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
+set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
+
+# Hidden visibilty is required for cxx on iOS
+set (CMAKE_C_FLAGS_INIT "")
+set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden")
+
+set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
+set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
+
+set (CMAKE_PLATFORM_HAS_INSTALLNAME 1)
+set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
+set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
+set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
+set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
+set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
+
+# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
+# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
+# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
+# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
+if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
+ find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
+endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
+
+# Setup iOS platform unless specified manually with IOS_PLATFORM
+if (NOT DEFINED IOS_PLATFORM)
+ set (IOS_PLATFORM "OS")
+endif (NOT DEFINED IOS_PLATFORM)
+set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
+
+# Setup building for arm64 or not
+if (NOT DEFINED BUILD_ARM64)
+ set (BUILD_ARM64 true)
+endif (NOT DEFINED BUILD_ARM64)
+set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not")
+
+# Check the platform selection and setup for developer root
+if (${IOS_PLATFORM} STREQUAL OS)
+ message (STATUS "Targeting iPhone platform")
+ set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
+
+ # This causes the installers to properly locate the output libraries
+ set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
+elseif (${IOS_PLATFORM} STREQUAL SIMULATOR)
+ message (STATUS "Targeting iPhoneSimulator platform")
+ set (SIMULATOR true)
+ set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
+
+ # This causes the installers to properly locate the output libraries
+ set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
+
+else (${IOS_PLATFORM} STREQUAL OS)
+ message (FATAL_ERROR "Unsupported IOS_PLATFORM value '${IOS_PLATFORM}' selected. Please choose OS or SIMULATOR")
+endif (${IOS_PLATFORM} STREQUAL OS)
+
+# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
+# Note Xcode 4.3 changed the installation location, choose the most recent one available
+exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR)
+set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
+set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
+if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
+ if (EXISTS ${XCODE_POST_43_ROOT})
+ set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
+ elseif(EXISTS ${XCODE_PRE_43_ROOT})
+ set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
+ endif (EXISTS ${XCODE_POST_43_ROOT})
+endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
+set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
+
+# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
+if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
+ file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
+ if (_CMAKE_IOS_SDKS)
+ list (SORT _CMAKE_IOS_SDKS)
+ list (REVERSE _CMAKE_IOS_SDKS)
+ list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
+ else (_CMAKE_IOS_SDKS)
+ message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
+ endif (_CMAKE_IOS_SDKS)
+ message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
+endif (NOT DEFINED CMAKE_IOS_SDK_ROOT)
+set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
+
+# Set the sysroot default to the most recent SDK
+set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
+message (STATUS "iOS sysroot=${CMAKE_OSX_SYSROOT}")
+
+# set the architecture for iOS
+if (${IOS_PLATFORM} STREQUAL OS)
+ set (OSX_UNIVERSAL true)
+ set (IOS_ARCH arm64)
+elseif (${IOS_PLATFORM} STREQUAL SIMULATOR)
+ set (IOS_ARCH x86_64)
+endif (${IOS_PLATFORM} STREQUAL OS)
+
+set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS" FORCE)
+set (CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS ${IOS_ARCH})
+message (STATUS "iOS architecture=${IOS_ARCH}")
+
+# Set the find root to the iOS developer roots and to user defined paths
+set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root")
+
+# default to searching for frameworks first
+set (CMAKE_FIND_FRAMEWORK FIRST)
+
+# set up the default search directories for frameworks
+set (CMAKE_SYSTEM_FRAMEWORK_PATH
+ ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
+ ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
+ ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
+)
+
+# only search the iOS sdks, not the remainder of the host filesystem
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+
+# This little macro lets you set any XCode specific property
+macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
+ set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
+endmacro (set_xcode_property)
+
+
+# This macro lets you find executable programs on the host system
+macro (find_host_package)
+ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+ set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
+ set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
+ set (IOS FALSE)
+
+ find_package(${ARGN})
+
+ set (IOS TRUE)
+ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+ set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+ set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endmacro (find_host_package)
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index df02266..123b44c 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -53,10 +53,10 @@ add_custom_target(doc ALL
# setup install rules
install(DIRECTORY ${DOXYGEN_OUTPUT_DIR}/html
- DESTINATION ${INSTALL_MISC_DIR}/doc
+ DESTINATION ${SFML_MISC_INSTALL_PREFIX}/doc
COMPONENT doc)
if(DOXYGEN_HHC_PROGRAM)
install(FILES ${DOXYGEN_OUTPUT_DIR}/sfml.chm
- DESTINATION ${INSTALL_MISC_DIR}/doc
+ DESTINATION ${SFML_MISC_INSTALL_PREFIX}/doc
COMPONENT doc)
endif()
diff --git a/doc/doxyfile.in b/doc/doxyfile.in
index 9a44a6a..104ff75 100644
--- a/doc/doxyfile.in
+++ b/doc/doxyfile.in
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.8.14
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -20,8 +20,8 @@
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
@@ -46,10 +46,10 @@ PROJECT_NUMBER = @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
@@ -60,7 +60,7 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIR@"
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
@@ -93,14 +93,14 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -145,7 +145,7 @@ ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = YES
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
@@ -215,9 +215,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
@@ -236,9 +236,27 @@ TAB_SIZE = 4
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
-ALIASES =
+#---------------------------------------------------------------------------
+# SFML specific aliases
+#---------------------------------------------------------------------------
+
+# sfplatform{platform(s)}
+# sfplatform{platform(s), header}
+#
+# Warns the user that some specific class or function is only available on
+# specific platforms.
+#
+# This shouldn't be used for incomplete implementations. It's meant for things
+# that will never appear on another platform, e.g. Android's native activity.
+#
+# If a header is given, the user is informed, that this header must be included
+# for the mentioned element to be defined.
+
+ALIASES = "sfplatform{1}=<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1.</b></dd></dl>" \
+ "sfplatform{2}=<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1</b> and to use it, you'll have to specifically include \2 in your code.</dd></dl>"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
@@ -286,7 +304,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
@@ -303,10 +321,19 @@ EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
@@ -328,7 +355,7 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
@@ -346,13 +373,20 @@ SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -411,7 +445,7 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -421,35 +455,35 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = NO
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
@@ -474,21 +508,21 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
+# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
@@ -502,7 +536,7 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
+# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
@@ -511,12 +545,19 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@@ -544,14 +585,14 @@ INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
@@ -596,27 +637,25 @@ SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
@@ -641,8 +680,8 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
@@ -687,7 +726,7 @@ LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
@@ -695,7 +734,7 @@ LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
@@ -706,7 +745,7 @@ CITE_BIB_FILES =
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
@@ -714,7 +753,7 @@ QUIET = NO
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
@@ -731,12 +770,18 @@ WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = YES
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
@@ -760,7 +805,7 @@ WARN_LOGFILE =
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = "@DOXYGEN_INPUT_DIR@/include/SFML" \
@@ -769,7 +814,7 @@ INPUT = "@DOXYGEN_INPUT_DIR@/include/SFML" \
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# The default value is: UTF-8.
@@ -777,12 +822,17 @@ INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.hpp
@@ -801,9 +851,10 @@ RECURSIVE = YES
EXCLUDE =
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
+# The default value is: NO.
EXCLUDE_SYMLINKS = NO
@@ -874,6 +925,10 @@ IMAGE_PATH =
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
@@ -883,11 +938,15 @@ INPUT_FILTER =
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
@@ -947,7 +1006,7 @@ REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
@@ -967,7 +1026,7 @@ SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
@@ -994,27 +1053,6 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES
-# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
-# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
-# cost of reduced performance. This can be particularly helpful with template
-# rich C++ code for which doxygen's built-in parser lacks the necessary type
-# information.
-# Note: The availability of this option depends on whether or not doxygen was
-# compiled with the --with-libclang option.
-# The default value is: NO.
-
-# Generates warnings with Clang
-#CLANG_ASSISTED_PARSING = NO
-
-# If clang assisted parsing is enabled you can provide the compiler with command
-# line options that you would normally use when invoking the compiler. Note that
-# the include paths will already be set by doxygen for the files and directories
-# specified with INPUT and INCLUDE_PATH.
-# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-
-# Generates warnings with Clang
-#CLANG_OPTIONS =
-
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -1031,7 +1069,7 @@ ALPHABETICAL_INDEX = YES
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-COLS_IN_ALPHA_INDEX = 5
+COLS_IN_ALPHA_INDEX = 3
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
@@ -1045,7 +1083,7 @@ IGNORE_PREFIX =
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
@@ -1107,18 +1145,14 @@ HTML_FOOTER = "@DOXYGEN_INPUT_DIR@/doc/footer.html"
HTML_STYLESHEET = "@DOXYGEN_INPUT_DIR@/doc/doxygen.css"
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1135,9 +1169,9 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
+# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
@@ -1166,12 +1200,24 @@ HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = NO
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
@@ -1195,12 +1241,12 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# environment (see: https://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1263,28 +1309,28 @@ GENERATE_HTMLHELP = @DOXYGEN_GENERATE_HTMLHELP@
CHM_FILE = ../SFML.chm
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION = "@DOXYGEN_HHC_PROGRAM@"
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1316,7 +1362,7 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1324,8 +1370,7 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1333,23 +1378,21 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
@@ -1398,7 +1441,7 @@ DISABLE_INDEX = NO
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1426,7 +1469,7 @@ ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1442,7 +1485,7 @@ EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
@@ -1454,8 +1497,8 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
@@ -1481,11 +1524,11 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
@@ -1541,9 +1584,9 @@ SERVER_BASED_SEARCH = NO
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see: https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1554,9 +1597,9 @@ EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
@@ -1592,7 +1635,7 @@ EXTRA_SEARCH_MAPPINGS =
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
@@ -1623,7 +1666,7 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1641,9 +1684,12 @@ COMPACT_LATEX = NO
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1658,9 +1704,9 @@ EXTRA_PACKAGES =
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
@@ -1676,6 +1722,17 @@ LATEX_HEADER =
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
@@ -1694,7 +1751,7 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1729,17 +1786,25 @@ LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
@@ -1754,7 +1819,7 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1791,11 +1856,21 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
@@ -1839,7 +1914,7 @@ MAN_LINKS = NO
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
@@ -1853,7 +1928,7 @@ GENERATE_XML = NO
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
@@ -1866,7 +1941,7 @@ XML_PROGRAMLISTING = YES
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
@@ -1880,7 +1955,7 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
@@ -1893,10 +1968,10 @@ DOCBOOK_PROGRAMLISTING = NO
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
@@ -1905,7 +1980,7 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
@@ -1913,7 +1988,7 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
@@ -1921,9 +1996,9 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
@@ -1943,14 +2018,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
@@ -1966,7 +2041,7 @@ MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2046,22 +2121,23 @@ TAGFILES =
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE = @DOXYGEN_OUTPUT_DIR@/SFML.tag
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
@@ -2078,7 +2154,7 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
@@ -2103,7 +2179,7 @@ MSCGEN_PATH =
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
@@ -2176,7 +2252,7 @@ COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
@@ -2228,7 +2304,8 @@ INCLUDED_BY_GRAPH = YES
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2239,7 +2316,8 @@ CALL_GRAPH = NO
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2262,11 +2340,15 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2314,10 +2396,19 @@ DIAFILE_DIRS =
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
@@ -2354,7 +2445,7 @@ MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
@@ -2371,27 +2462,9 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# SFML specific aliases
-#---------------------------------------------------------------------------
-
-# sfplatform{platform(s)}
-# sfplatform{platform(s), header}
-#
-# Warns the user that some specific class or function is only available on
-# specific platforms.
-#
-# This shouldn't be used for incomplete implementations. It's meant for things
-# that will never appear on another platform, e.g. Android's native activity.
-#
-# If a header is given, the user is informed, that this header must be included
-# for the mentioned element to be defined.
-ALIASES += sfplatform{1}="<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1.</b></dd></dl>"
-ALIASES += sfplatform{2}="<dl class=\"attention\"><dt>Platform Limitation</dt><dd><b>This is only available on \1</b> and to use it, you'll have to specifically include \2 in your code.</dd></dl>"
diff --git a/doc/doxygen.css b/doc/doxygen.css
index ed4e6e4..9c2fc6a 100644
--- a/doc/doxygen.css
+++ b/doc/doxygen.css
@@ -415,6 +415,10 @@ table.memberdecls {
margin-left: 9px;
}
+.memtitle {
+ display: none;
+}
+
.memnav {
background-color: #EBEFF6;
border: 1px solid #A3B4D7;
@@ -1440,4 +1444,7 @@ div.contents ul li {
border-width: 11px;
top: 50%;
margin-top: -11px;
-} \ No newline at end of file
+}
+.arrow {
+ cursor: pointer;
+}
diff --git a/doc/footer.html b/doc/footer.html
index 0e7569a..c9cd937 100644
--- a/doc/footer.html
+++ b/doc/footer.html
@@ -1,7 +1,7 @@
</div>
<div id="footer-container">
<div id="footer">
- SFML is licensed under the terms and conditions of the <a href="http://www.sfml-dev.org/license.php">zlib/png license</a>.<br>
+ SFML is licensed under the terms and conditions of the <a href="https://www.sfml-dev.org/license.php">zlib/png license</a>.<br>
Copyright &copy; Laurent Gomila &nbsp;::&nbsp;
Documentation generated by <a href="http://www.doxygen.org/" title="doxygen website">doxygen</a> &nbsp;::&nbsp;
</div>
diff --git a/doc/header.html.in b/doc/header.html.in
index 34337fd..cc42ea2 100644
--- a/doc/header.html.in
+++ b/doc/header.html.in
@@ -4,7 +4,7 @@
<title>SFML - Simple and Fast Multimedia Library</title>
<meta http-equiv="Content-Type" content="text/html;"/>
<meta charset="utf-8"/>
- <!--<link rel='stylesheet' type='text/css' href="http://fonts.googleapis.com/css?family=Ubuntu:400,700,400italic"/>-->
+ <!--<link rel='stylesheet' type='text/css' href="https://fonts.googleapis.com/css?family=Ubuntu:400,700,400italic"/>-->
<link rel="stylesheet" type="text/css" href="doxygen.css" title="default" media="screen,print" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
diff --git a/doc/mainpage.hpp b/doc/mainpage.hpp
index 7ef4b6f..16f2c43 100644
--- a/doc/mainpage.hpp
+++ b/doc/mainpage.hpp
@@ -5,7 +5,7 @@
/// Welcome to the official SFML documentation. Here you will find a detailed
/// view of all the SFML <a href="./annotated.php">classes</a> and functions. <br/>
/// If you are looking for tutorials, you can visit the official website
-/// at <a href="http://www.sfml-dev.org/">www.sfml-dev.org</a>.
+/// at <a href="https://www.sfml-dev.org/">www.sfml-dev.org</a>.
///
/// \section example Short example
/// Here is a short example, to show you how simple it is to use SFML:
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index a55137d..a13f585 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,18 +1,38 @@
-# add the examples subdirectories
-add_subdirectory(ftp)
-add_subdirectory(opengl)
-add_subdirectory(pong)
-add_subdirectory(shader)
-add_subdirectory(sockets)
-add_subdirectory(sound)
-add_subdirectory(sound_capture)
-add_subdirectory(voip)
-add_subdirectory(window)
-if(SFML_OS_WINDOWS)
- add_subdirectory(win32)
-elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
- add_subdirectory(X11)
-elseif(SFML_OS_MACOSX)
- add_subdirectory(cocoa)
-endif()
+# iOS Demo
+if(SFML_OS_IOS)
+ add_subdirectory(iOS)
+else(SFML_OS_IOS)
+
+ # add the examples subdirectories
+ if(SFML_BUILD_NETWORK)
+ add_subdirectory(ftp)
+ add_subdirectory(sockets)
+ endif()
+ if(SFML_BUILD_NETWORK AND SFML_BUILD_AUDIO)
+ add_subdirectory(voip)
+ endif()
+ if(SFML_BUILD_AUDIO)
+ add_subdirectory(sound)
+ add_subdirectory(sound_capture)
+ endif()
+ if(SFML_BUILD_WINDOW)
+ add_subdirectory(window)
+ endif()
+ if(SFML_BUILD_GRAPHICS)
+ add_subdirectory(joystick)
+ add_subdirectory(opengl)
+ add_subdirectory(shader)
+ add_subdirectory(island)
+ if(SFML_OS_WINDOWS)
+ add_subdirectory(win32)
+ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
+ add_subdirectory(X11)
+ elseif(SFML_OS_MACOSX)
+ add_subdirectory(cocoa)
+ endif()
+ endif()
+ if(SFML_BUILD_GRAPHICS AND SFML_BUILD_AUDIO)
+ add_subdirectory(pong)
+ endif()
+endif(SFML_OS_IOS) \ No newline at end of file
diff --git a/examples/X11/CMakeLists.txt b/examples/X11/CMakeLists.txt
index cc62f48..27509a6 100644
--- a/examples/X11/CMakeLists.txt
+++ b/examples/X11/CMakeLists.txt
@@ -4,13 +4,7 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/X11)
# all source files
set(SRC ${SRCROOT}/X11.cpp)
-# find OpenGL and X11
-find_package(OpenGL REQUIRED)
-include_directories(${OPENGL_INCLUDE_DIR})
-find_package(X11 REQUIRED)
-include_directories(${X11_INCLUDE_DIR})
-
# define the X11 target
-sfml_add_example(X11 GUI_APP
+sfml_add_example(X11Example GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-window sfml-system ${OPENGL_LIBRARIES} ${X11_LIBRARIES})
+ DEPENDS sfml-window OpenGL X11)
diff --git a/examples/android/.gitignore b/examples/android/.gitignore
new file mode 100644
index 0000000..a76e965
--- /dev/null
+++ b/examples/android/.gitignore
@@ -0,0 +1,8 @@
+local.properties
+.idea
+.gradle
+build
+android.iml
+app/build
+app/.externalNativeBuild
+app/src/main/obj
diff --git a/examples/android/app/app.iml b/examples/android/app/app.iml
new file mode 100644
index 0000000..232000a
--- /dev/null
+++ b/examples/android/app/app.iml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":app" />
+ </configuration>
+ </facet>
+ <facet type="native-android-gradle" name="Native-Android-Gradle">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+ <afterSyncTasks>
+ <task>generateDebugSources</task>
+ </afterSyncTasks>
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/main/cpp" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes-jar" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndkBuild" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/examples/android/app/build.gradle b/examples/android/app/build.gradle
new file mode 100644
index 0000000..b1fb031
--- /dev/null
+++ b/examples/android/app/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 27
+ defaultConfig {
+ applicationId "org.sfmldev.android"
+ minSdkVersion 14
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ externalNativeBuild {
+ ndkBuild {
+ // cppFlags "-std=c++14 -frtti -fexceptions"
+ }
+
+ }
+ ndk {
+ abiFilters 'armeabi-v7a'
+ }
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ externalNativeBuild {
+ ndkBuild {
+ path "src/main/jni/Android.mk"
+
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/examples/android/app/proguard-rules.pro b/examples/android/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/examples/android/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/examples/android/AndroidManifest.xml b/examples/android/app/src/main/AndroidManifest.xml
index edee84f..20fbbe5 100644
--- a/examples/android/AndroidManifest.xml
+++ b/examples/android/app/src/main/AndroidManifest.xml
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.sfml"
+ package="org.sfmldev.android"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature android:glEsVersion="0x00010001" />
- <uses-sdk android:minSdkVersion="9"
+ <uses-sdk android:minSdkVersion="14"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE" />
-
+
<application android:label="@string/app_name"
android:icon="@drawable/sfml_logo"
android:hasCode="false"
@@ -22,7 +22,7 @@
android:icon="@drawable/sfml_logo"
android:configChanges="keyboardHidden|orientation|screenSize">
- <meta-data android:name="android.app.lib_name" android:value="sfml-activity" />
+ <meta-data android:name="android.app.lib_name" android:value="sfml-activity-d" />
<meta-data android:name="sfml.app.lib_name" android:value="sfml-example" />
<intent-filter>
diff --git a/examples/android/assets/image.png b/examples/android/app/src/main/assets/image.png
index 29ba010..29ba010 100644
--- a/examples/android/assets/image.png
+++ b/examples/android/app/src/main/assets/image.png
Binary files differ
diff --git a/examples/android/assets/sansation.ttf b/examples/android/app/src/main/assets/sansation.ttf
index d85fbc8..d85fbc8 100644
--- a/examples/android/assets/sansation.ttf
+++ b/examples/android/app/src/main/assets/sansation.ttf
Binary files differ
diff --git a/examples/android/app/src/main/jni/Android.mk b/examples/android/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..e848c11
--- /dev/null
+++ b/examples/android/app/src/main/jni/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := sfml-example
+
+LOCAL_SRC_FILES := main.cpp
+
+LOCAL_SHARED_LIBRARIES := sfml-system-d
+LOCAL_SHARED_LIBRARIES += sfml-window-d
+LOCAL_SHARED_LIBRARIES += sfml-graphics-d
+LOCAL_SHARED_LIBRARIES += sfml-audio-d
+LOCAL_SHARED_LIBRARIES += sfml-network-d
+LOCAL_SHARED_LIBRARIES += sfml-activity-d
+LOCAL_SHARED_LIBRARIES += openal
+LOCAL_WHOLE_STATIC_LIBRARIES := sfml-main-d
+
+include $(BUILD_SHARED_LIBRARY)
+
+$(call import-module,third_party/sfml)
diff --git a/examples/android/app/src/main/jni/Application.mk b/examples/android/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..df10f28
--- /dev/null
+++ b/examples/android/app/src/main/jni/Application.mk
@@ -0,0 +1,8 @@
+NDK_TOOLCHAIN_VERSION := 4.9
+APP_PLATFORM := android-14
+# APP_STL has to match CMAKE_ANDROID_STL_TYPE
+APP_STL := c++_static
+APP_ABI := armeabi-v7a
+APP_MODULES := sfml-activity-d sfml-example
+APP_OPTIM := debug
+APP_CFLAG := -g -ggdb -O0 \ No newline at end of file
diff --git a/examples/android/jni/main.cpp b/examples/android/app/src/main/jni/main.cpp
index 56b6741..e5445b5 100644
--- a/examples/android/jni/main.cpp
+++ b/examples/android/app/src/main/jni/main.cpp
@@ -76,40 +76,79 @@ int vibrate(sf::Time duration)
// ('vibrate()' in this example; undefine 'USE_JNI' above to disable it)
int main(int argc, char *argv[])
{
- sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
+ sf::VideoMode screen(sf::VideoMode::getDesktopMode());
+
+ sf::RenderWindow window(screen, "");
+ window.setFramerateLimit(30);
sf::Texture texture;
if(!texture.loadFromFile("image.png"))
return EXIT_FAILURE;
sf::Sprite image(texture);
- image.setPosition(0, 0);
+ image.setPosition(screen.width / 2, screen.height / 2);
image.setOrigin(texture.getSize().x/2, texture.getSize().y/2);
- sf::Music music;
+ sf::Font font;
+ if (!font.loadFromFile("sansation.ttf"))
+ return EXIT_FAILURE;
+
+ sf::Text text("Tap anywhere to move the logo.", font, 64);
+ text.setFillColor(sf::Color::Black);
+ text.setPosition(10, 10);
+
+ // Loading canary.wav fails for me for now; haven't had time to test why
+
+ /*sf::Music music;
if(!music.openFromFile("canary.wav"))
return EXIT_FAILURE;
- music.play();
+ music.play();*/
sf::View view = window.getDefaultView();
+ sf::Color background = sf::Color::White;
+
+ // We shouldn't try drawing to the screen while in background
+ // so we'll have to track that. You can do minor background
+ // work, but keep battery life in mind.
+ bool active = true;
+
while (window.isOpen())
{
sf::Event event;
- while (window.pollEvent(event))
+ while (active ? window.pollEvent(event) : window.waitEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
+ case sf::Event::KeyPressed:
+ if (event.key.code == sf::Keyboard::Escape)
+ window.close();
+ break;
case sf::Event::Resized:
view.setSize(event.size.width, event.size.height);
view.setCenter(event.size.width/2, event.size.height/2);
window.setView(view);
break;
+ case sf::Event::LostFocus:
+ background = sf::Color::Black;
+ break;
+ case sf::Event::GainedFocus:
+ background = sf::Color::White;
+ break;
+
+ // On Android MouseLeft/MouseEntered are (for now) triggered,
+ // whenever the app loses or gains focus.
+ case sf::Event::MouseLeft:
+ active = false;
+ break;
+ case sf::Event::MouseEntered:
+ active = true;
+ break;
case sf::Event::TouchBegan:
if (event.touch.finger == 0)
{
@@ -122,8 +161,15 @@ int main(int argc, char *argv[])
}
}
- window.clear(sf::Color::White);
- window.draw(image);
- window.display();
+ if (active)
+ {
+ window.clear(background);
+ window.draw(image);
+ window.draw(text);
+ window.display();
+ }
+ else {
+ sf::sleep(sf::milliseconds(100));
+ }
}
}
diff --git a/examples/android/res/drawable-hdpi/sfml_logo.png b/examples/android/app/src/main/res/drawable-hdpi/sfml_logo.png
index 7bae333..7bae333 100644
--- a/examples/android/res/drawable-hdpi/sfml_logo.png
+++ b/examples/android/app/src/main/res/drawable-hdpi/sfml_logo.png
Binary files differ
diff --git a/examples/android/res/drawable-ldpi/sfml_logo.png b/examples/android/app/src/main/res/drawable-ldpi/sfml_logo.png
index 6552c56..6552c56 100644
--- a/examples/android/res/drawable-ldpi/sfml_logo.png
+++ b/examples/android/app/src/main/res/drawable-ldpi/sfml_logo.png
Binary files differ
diff --git a/examples/android/res/drawable-mdpi/sfml_logo.png b/examples/android/app/src/main/res/drawable-mdpi/sfml_logo.png
index 8778688..8778688 100644
--- a/examples/android/res/drawable-mdpi/sfml_logo.png
+++ b/examples/android/app/src/main/res/drawable-mdpi/sfml_logo.png
Binary files differ
diff --git a/examples/android/res/drawable-xhdpi/sfml_logo.png b/examples/android/app/src/main/res/drawable-xhdpi/sfml_logo.png
index ff0d3aa..ff0d3aa 100644
--- a/examples/android/res/drawable-xhdpi/sfml_logo.png
+++ b/examples/android/app/src/main/res/drawable-xhdpi/sfml_logo.png
Binary files differ
diff --git a/examples/android/res/drawable-xxhdpi/sfml_logo.png b/examples/android/app/src/main/res/drawable-xxhdpi/sfml_logo.png
index 8a66e84..8a66e84 100644
--- a/examples/android/res/drawable-xxhdpi/sfml_logo.png
+++ b/examples/android/app/src/main/res/drawable-xxhdpi/sfml_logo.png
Binary files differ
diff --git a/examples/android/res/values/strings.xml b/examples/android/app/src/main/res/values/strings.xml
index acedde6..acedde6 100644
--- a/examples/android/res/values/strings.xml
+++ b/examples/android/app/src/main/res/values/strings.xml
diff --git a/examples/android/build.gradle b/examples/android/build.gradle
new file mode 100644
index 0000000..56292ed
--- /dev/null
+++ b/examples/android/build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.0.0'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/examples/android/gradle.properties b/examples/android/gradle.properties
new file mode 100644
index 0000000..aac7c9b
--- /dev/null
+++ b/examples/android/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/examples/android/jni/Android.mk b/examples/android/jni/Android.mk
deleted file mode 100644
index 8c42b78..0000000
--- a/examples/android/jni/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := sfml-example
-
-LOCAL_SRC_FILES := main.cpp
-
-LOCAL_SHARED_LIBRARIES := sfml-system
-LOCAL_SHARED_LIBRARIES += sfml-window
-LOCAL_SHARED_LIBRARIES += sfml-graphics
-LOCAL_SHARED_LIBRARIES += sfml-audio
-LOCAL_SHARED_LIBRARIES += sfml-network
-LOCAL_WHOLE_STATIC_LIBRARIES := sfml-main
-
-include $(BUILD_SHARED_LIBRARY)
-
-$(call import-module,sfml)
diff --git a/examples/android/jni/Application.mk b/examples/android/jni/Application.mk
deleted file mode 100644
index 71828c8..0000000
--- a/examples/android/jni/Application.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-NDK_TOOLCHAIN_VERSION := 4.9
-APP_PLATFORM := android-9
-APP_STL := c++_shared
-APP_ABI := armeabi-v7a
-APP_MODULES := sfml-activity sfml-example
diff --git a/examples/android/settings.gradle b/examples/android/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/examples/android/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/examples/cocoa/CMakeLists.txt b/examples/cocoa/CMakeLists.txt
index 5f67a1d..ff63cc0 100644
--- a/examples/cocoa/CMakeLists.txt
+++ b/examples/cocoa/CMakeLists.txt
@@ -1,6 +1,34 @@
set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/cocoa)
+# Usage: compile_xib(INPUT path/to/file.xib OUTPUT path/to/file.nib)
+function(compile_xib)
+ cmake_parse_arguments(THIS "" "INPUT;OUTPUT" "" ${ARGN})
+ if (NOT THIS_INPUT)
+ message(FATAL_ERROR "Missing required argument INPUT in call to compile_xib()")
+ endif()
+
+ if (NOT THIS_OUTPUT)
+ message(FATAL_ERROR "Missing required argument OUTPUT in call to compile_xib()")
+ endif()
+
+ if (NOT DEFINED IBTOOL)
+ find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
+ endif()
+ if(NOT IBTOOL)
+ message(FATAL_ERROR "ibtool is required to compile .xib files but wasn't found.")
+ endif()
+
+ # Default args taken from Xcode 9 when it generates a nib from a xib
+ set(DEFAULT_ARGS --errors --warnings --notices --module cocoa --auto-activate-custom-fonts --target-device mac --minimum-deployment-target ${CMAKE_OSX_DEPLOYMENT_TARGET} --output-format human-readable-text)
+
+ add_custom_command(OUTPUT "${THIS_OUTPUT}"
+ COMMAND "${IBTOOL}" ${DEFAULT_ARGS} "${THIS_INPUT}" --compile "${THIS_OUTPUT}"
+ DEPENDS "${THIS_INPUT}"
+ COMMENT "Generating ${THIS_OUTPUT}"
+ VERBATIM)
+endfunction()
+
# all source files
set(SRC ${SRCROOT}/CocoaAppDelegate.h
${SRCROOT}/CocoaAppDelegate.mm
@@ -8,8 +36,7 @@ set(SRC ${SRCROOT}/CocoaAppDelegate.h
${SRCROOT}/NSString+stdstring.mm
${SRCROOT}/main.m)
-# all XIB files
-set(XIBS MainMenu)
+compile_xib(INPUT "${SRCROOT}/MainMenu.xib" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/MainMenu.nib")
# all resource files
set(RESOURCES ${SRCROOT}/resources/logo.png
@@ -18,50 +45,17 @@ set(RESOURCES ${SRCROOT}/resources/logo.png
${SRCROOT}/resources/blue.png
${SRCROOT}/resources/green.png
${SRCROOT}/resources/red.png
- ${SRCROOT}/resources/Credits.rtf)
-
-# define the cocoa target and customize it
-add_executable(cocoa MACOSX_BUNDLE ${SRC} ${RESOURCES})
+ ${SRCROOT}/resources/Credits.rtf
+ ${CMAKE_CURRENT_BINARY_DIR}/MainMenu.nib)
set_source_files_properties(${RESOURCES} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
+
+# define the cocoa target and customize it
+sfml_add_example(cocoa
+ SOURCES ${SRC}
+ BUNDLE_RESOURCES ${RESOURCES}
+ DEPENDS sfml-system sfml-window sfml-graphics)
set_target_properties(cocoa PROPERTIES
+ MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${SRCROOT}/resources/Cocoa-Info.plist)
-target_link_libraries(cocoa "-framework Cocoa -framework Foundation"
- sfml-system sfml-window sfml-graphics)
-
-# set the target's folder (for IDEs that support it, e.g. Visual Studio)
-set_target_properties(cocoa PROPERTIES FOLDER "Examples")
-
-# compile XIB files
-find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
-if(${IBTOOL} STREQUAL "IBTOOL-NOTFOUND")
- message(FATAL_ERROR "ibtool is required to compile .xib files but wasn't found.")
-endif()
-set(RESOURCE_PATH "cocoa.app/Contents/Resources")
-set(XIB_OUTPUT_PATH "${RESOURCE_PATH}/")
-set(XIB_INPUT_PATH "${SRCROOT}/")
-foreach(XIB ${XIBS})
- add_custom_command(TARGET cocoa
- POST_BUILD
- COMMAND ${IBTOOL} --errors
- --output-format human-readable-text
- --compile ${XIB_OUTPUT_PATH}/${XIB}.nib
- ${XIB_INPUT_PATH}/${XIB}.xib
- COMMENT "Compiling ${XIB}.xib")
- # deactivated options: --warnings --notices
-endforeach()
-
-# add install rule
-install(TARGETS cocoa
- BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/cocoa
- COMPONENT examples)
-
-#
-# define the cocoa target
-# sfml_add_example is not compatible with application bundles !
-#
-#sfml_add_example(cocoa
-# SOURCES ${SRC}
-# DEPENDS sfml-system sfml-window sfml-graphics)
-#
-
+target_link_libraries(cocoa PRIVATE "-framework Cocoa" "-framework Foundation" sfml-graphics)
diff --git a/examples/cocoa/CocoaAppDelegate.h b/examples/cocoa/CocoaAppDelegate.h
index fed5b52..9dab138 100644
--- a/examples/cocoa/CocoaAppDelegate.h
+++ b/examples/cocoa/CocoaAppDelegate.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/examples/cocoa/CocoaAppDelegate.mm b/examples/cocoa/CocoaAppDelegate.mm
index 3996b3a..a58ca87 100644
--- a/examples/cocoa/CocoaAppDelegate.mm
+++ b/examples/cocoa/CocoaAppDelegate.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/examples/cocoa/NSString+stdstring.h b/examples/cocoa/NSString+stdstring.h
index 0021ef9..cce9bd8 100644
--- a/examples/cocoa/NSString+stdstring.h
+++ b/examples/cocoa/NSString+stdstring.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/examples/cocoa/NSString+stdstring.mm b/examples/cocoa/NSString+stdstring.mm
index d2ce03b..92b7984 100644
--- a/examples/cocoa/NSString+stdstring.mm
+++ b/examples/cocoa/NSString+stdstring.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -65,7 +65,7 @@
-(std::wstring)tostdwstring
{
// According to Wikipedia, Mac OS X is Little Endian on x86 and x86-64
- // http://en.wikipedia.org/wiki/Endianness
+ // https://en.wikipedia.org/wiki/Endianness
NSData* asData = [self dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
diff --git a/examples/cocoa/main.m b/examples/cocoa/main.m
index a66e33a..b7aa944 100644
--- a/examples/cocoa/main.m
+++ b/examples/cocoa/main.m
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/examples/cocoa/resources/Cocoa-Info.plist b/examples/cocoa/resources/Cocoa-Info.plist
index 3bbc608..1348f3c 100644
--- a/examples/cocoa/resources/Cocoa-Info.plist
+++ b/examples/cocoa/resources/Cocoa-Info.plist
@@ -25,7 +25,7 @@
<key>LSMinimumSystemVersion</key>
<string>10.6</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright © 2007-2017 Marco Antognini and Laurent Gomila. Shared under zlib/libpng License.</string>
+ <string>Copyright © 2007-2018 Marco Antognini and Laurent Gomila. Shared under zlib/libpng License.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
diff --git a/examples/cocoa/resources/Credits.rtf b/examples/cocoa/resources/Credits.rtf
index 53942fc..ed40d67 100644
--- a/examples/cocoa/resources/Credits.rtf
+++ b/examples/cocoa/resources/Credits.rtf
@@ -4,4 +4,4 @@
\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qj
-\f0\fs24 \cf0 See {\field{\*\fldinst{HYPERLINK "http://sfml-dev.org"}}{\fldrslt http://sfml-dev.org}} for more information} \ No newline at end of file
+\f0\fs24 \cf0 See {\field{\*\fldinst{HYPERLINK "https://sfml-dev.org"}}{\fldrslt https://sfml-dev.org}} for more information}
diff --git a/examples/ftp/CMakeLists.txt b/examples/ftp/CMakeLists.txt
index b154e5e..a65cb67 100644
--- a/examples/ftp/CMakeLists.txt
+++ b/examples/ftp/CMakeLists.txt
@@ -7,4 +7,4 @@ set(SRC ${SRCROOT}/Ftp.cpp)
# define the ftp target
sfml_add_example(ftp
SOURCES ${SRC}
- DEPENDS sfml-network sfml-system)
+ DEPENDS sfml-network)
diff --git a/examples/iOS/CMakeLists.txt b/examples/iOS/CMakeLists.txt
new file mode 100644
index 0000000..96450f4
--- /dev/null
+++ b/examples/iOS/CMakeLists.txt
@@ -0,0 +1,25 @@
+
+set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/iOS)
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
+
+# All source files
+set(SRC ${SRCROOT}/main.cpp)
+
+set(RESOURCES
+ ${SRCROOT}/resources/canary.wav
+ ${SRCROOT}/resources/image.png
+ ${SRCROOT}/resources/orchestral.ogg
+ ${SRCROOT}/resources/sansation.ttf)
+
+set_source_files_properties( ${RESOURCES} PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources )
+
+# Define the window target
+sfml_add_example(ios_demo GUI_APP
+ SOURCES ${SRC} ${RESOURCES}
+ DEPENDS sfml-window sfml-system sfml-graphics sfml-audio
+ "-framework OpenGLES")
+
+# The app needs an identifier and signing to work correctly
+SET_XCODE_PROPERTY(ios_demo CODE_SIGN_IDENTITY "iPhone Developer")
+set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.sfml.ios_demo")
diff --git a/examples/iOS/main.cpp b/examples/iOS/main.cpp
new file mode 100644
index 0000000..473b2b9
--- /dev/null
+++ b/examples/iOS/main.cpp
@@ -0,0 +1,65 @@
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Graphics.hpp>
+#include <SFML/Audio.hpp>
+#include <SFML/Main.hpp>
+
+
+////////////////////////////////////////////////////////////
+/// Entry point of application
+///
+/// \return Application exit code
+///
+////////////////////////////////////////////////////////////
+int main()
+{
+ sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
+
+ sf::Texture texture;
+ if(!texture.loadFromFile("image.png"))
+ return EXIT_FAILURE;
+
+ sf::Sprite image(texture);
+ image.setPosition(0, 0);
+ image.setOrigin(texture.getSize().x/2, texture.getSize().y/2);
+
+ sf::Music music;
+ if(!music.openFromFile("canary.wav"))
+ return EXIT_FAILURE;
+
+ music.play();
+
+ sf::View view = window.getDefaultView();
+
+ while (window.isOpen())
+ {
+ sf::Event event;
+
+ while (window.pollEvent(event))
+ {
+ switch (event.type)
+ {
+ case sf::Event::Closed:
+ window.close();
+ break;
+ case sf::Event::Resized:
+ view.setSize(event.size.width, event.size.height);
+ view.setCenter(event.size.width/2, event.size.height/2);
+ window.setView(view);
+ break;
+ case sf::Event::TouchBegan:
+ if (event.touch.finger == 0)
+ {
+ image.setPosition(event.touch.x, event.touch.y);
+ }
+ break;
+ }
+ }
+
+ window.clear(sf::Color::White);
+ window.draw(image);
+ window.display();
+ }
+}
+
diff --git a/examples/iOS/resources/image.png b/examples/iOS/resources/image.png
new file mode 100644
index 0000000..29ba010
--- /dev/null
+++ b/examples/iOS/resources/image.png
Binary files differ
diff --git a/examples/iOS/resources/sansation.ttf b/examples/iOS/resources/sansation.ttf
new file mode 100644
index 0000000..d85fbc8
--- /dev/null
+++ b/examples/iOS/resources/sansation.ttf
Binary files differ
diff --git a/examples/island/CMakeLists.txt b/examples/island/CMakeLists.txt
new file mode 100644
index 0000000..38428e3
--- /dev/null
+++ b/examples/island/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/island)
+
+# all source files
+set(SRC ${SRCROOT}/Island.cpp)
+
+# define the island target
+sfml_add_example(island GUI_APP
+ SOURCES ${SRC}
+ DEPENDS sfml-graphics sfml-window sfml-system
+ RESOURCES_DIR resources) \ No newline at end of file
diff --git a/examples/island/Island.cpp b/examples/island/Island.cpp
new file mode 100644
index 0000000..50a8f1e
--- /dev/null
+++ b/examples/island/Island.cpp
@@ -0,0 +1,590 @@
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#define STB_PERLIN_IMPLEMENTATION
+#include "stb_perlin.h"
+#include <SFML/Graphics.hpp>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <algorithm>
+#include <cstring>
+#include <cmath>
+
+
+namespace
+{
+ // Width and height of the application window
+ const unsigned int windowWidth = 800;
+ const unsigned int windowHeight = 600;
+
+ // Resolution of the generated terrain
+ const unsigned int resolutionX = 800;
+ const unsigned int resolutionY = 600;
+
+ // Thread pool parameters
+ const unsigned int threadCount = 4;
+ const unsigned int blockCount = 32;
+
+ struct WorkItem
+ {
+ sf::Vertex* targetBuffer;
+ unsigned int index;
+ };
+
+ std::deque<WorkItem> workQueue;
+ std::vector<sf::Thread*> threads;
+ int pendingWorkCount = 0;
+ bool workPending = true;
+ bool bufferUploadPending = false;
+ sf::Mutex workQueueMutex;
+
+ struct Setting
+ {
+ const char* name;
+ float* value;
+ };
+
+ // Terrain noise parameters
+ const int perlinOctaves = 3;
+
+ float perlinFrequency = 7.0f;
+ float perlinFrequencyBase = 4.0f;
+
+ // Terrain generation parameters
+ float heightBase = 0.0f;
+ float edgeFactor = 0.9f;
+ float edgeDropoffExponent = 1.5f;
+
+ float snowcapHeight = 0.6f;
+
+ // Terrain lighting parameters
+ float heightFactor = windowHeight / 2.0f;
+ float heightFlatten = 3.0f;
+ float lightFactor = 0.7f;
+}
+
+
+// Forward declarations of the functions we define further down
+void threadFunction();
+void generateTerrain(sf::Vertex* vertexBuffer);
+
+
+////////////////////////////////////////////////////////////
+/// Entry point of application
+///
+/// \return Application exit code
+///
+////////////////////////////////////////////////////////////
+int main()
+{
+ // Create the window of the application
+ sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML Island",
+ sf::Style::Titlebar | sf::Style::Close);
+ window.setVerticalSyncEnabled(true);
+
+ sf::Font font;
+ if (!font.loadFromFile("resources/sansation.ttf"))
+ return EXIT_FAILURE;
+
+ // Create all of our graphics resources
+ sf::Text hudText;
+ sf::Text statusText;
+ sf::Shader terrainShader;
+ sf::RenderStates terrainStates(&terrainShader);
+ sf::VertexBuffer terrain(sf::Triangles, sf::VertexBuffer::Static);
+
+ // Set up our text drawables
+ statusText.setFont(font);
+ statusText.setCharacterSize(28);
+ statusText.setFillColor(sf::Color::White);
+ statusText.setOutlineColor(sf::Color::Black);
+ statusText.setOutlineThickness(2.0f);
+
+ hudText.setFont(font);
+ hudText.setCharacterSize(14);
+ hudText.setFillColor(sf::Color::White);
+ hudText.setOutlineColor(sf::Color::Black);
+ hudText.setOutlineThickness(2.0f);
+ hudText.setPosition(5.0f, 5.0f);
+
+ // Staging buffer for our terrain data that we will upload to our VertexBuffer
+ std::vector<sf::Vertex> terrainStagingBuffer;
+
+ // Check whether the prerequisites are suppprted
+ bool prerequisitesSupported = sf::VertexBuffer::isAvailable() && sf::Shader::isAvailable();
+
+ // Set up our graphics resources and set the status text accordingly
+ if (!prerequisitesSupported)
+ {
+ statusText.setString("Shaders and/or Vertex Buffers Unsupported");
+ }
+ else if (!terrainShader.loadFromFile("resources/terrain.vert", "resources/terrain.frag"))
+ {
+ prerequisitesSupported = false;
+
+ statusText.setString("Failed to load shader program");
+ }
+ else
+ {
+ // Start up our thread pool
+ for (unsigned int i = 0; i < threadCount; i++)
+ {
+ threads.push_back(new sf::Thread(threadFunction));
+ threads.back()->launch();
+ }
+
+ // Create our VertexBuffer with enough space to hold all the terrain geometry
+ terrain.create(resolutionX * resolutionY * 6);
+
+ // Resize the staging buffer to be able to hold all the terrain geometry
+ terrainStagingBuffer.resize(resolutionX * resolutionY * 6);
+
+ // Generate the initial terrain
+ generateTerrain(&terrainStagingBuffer[0]);
+
+ statusText.setString("Generating Terrain...");
+ }
+
+ // Center the status text
+ statusText.setPosition((windowWidth - statusText.getLocalBounds().width) / 2.f, (windowHeight - statusText.getLocalBounds().height) / 2.f);
+
+ // Set up an array of pointers to our settings for arrow navigation
+ Setting settings[] =
+ {
+ {"perlinFrequency", &perlinFrequency},
+ {"perlinFrequencyBase", &perlinFrequencyBase},
+ {"heightBase", &heightBase},
+ {"edgeFactor", &edgeFactor},
+ {"edgeDropoffExponent", &edgeDropoffExponent},
+ {"snowcapHeight", &snowcapHeight},
+ {"heightFactor", &heightFactor},
+ {"heightFlatten", &heightFlatten},
+ {"lightFactor", &lightFactor}
+ };
+
+ const int settingCount = 9;
+ int currentSetting = 0;
+
+ std::ostringstream osstr;
+ sf::Clock clock;
+
+ while (window.isOpen())
+ {
+ // Handle events
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ // Window closed or escape key pressed: exit
+ if ((event.type == sf::Event::Closed) ||
+ ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
+ {
+ window.close();
+ break;
+ }
+
+ // Arrow key pressed:
+ if (prerequisitesSupported && (event.type == sf::Event::KeyPressed))
+ {
+ switch (event.key.code)
+ {
+ case sf::Keyboard::Return: generateTerrain(&terrainStagingBuffer[0]); break;
+ case sf::Keyboard::Down: currentSetting = (currentSetting + 1) % settingCount; break;
+ case sf::Keyboard::Up: currentSetting = (currentSetting + settingCount - 1) % settingCount; break;
+ case sf::Keyboard::Left: *(settings[currentSetting].value) -= 0.1f; break;
+ case sf::Keyboard::Right: *(settings[currentSetting].value) += 0.1f; break;
+ default: break;
+ }
+ }
+ }
+
+ // Clear, draw graphics objects and display
+ window.clear();
+
+ window.draw(statusText);
+
+ if (prerequisitesSupported)
+ {
+ {
+ sf::Lock lock(workQueueMutex);
+
+ // Don't bother updating/drawing the VertexBuffer while terrain is being regenerated
+ if (!pendingWorkCount)
+ {
+ // If there is new data pending to be uploaded to the VertexBuffer, do it now
+ if (bufferUploadPending)
+ {
+ terrain.update(&terrainStagingBuffer[0]);
+ bufferUploadPending = false;
+ }
+
+ terrainShader.setUniform("lightFactor", lightFactor);
+ window.draw(terrain, terrainStates);
+ }
+ }
+
+ // Update and draw the HUD text
+ osstr.str("");
+ osstr << "Frame: " << clock.restart().asMilliseconds() << "ms\n"
+ << "perlinOctaves: " << perlinOctaves << "\n\n"
+ << "Use the arrow keys to change the values.\nUse the return key to regenerate the terrain.\n\n";
+
+ for (int i = 0; i < settingCount; ++i)
+ osstr << ((i == currentSetting) ? ">> " : " ") << settings[i].name << ": " << *(settings[i].value) << "\n";
+
+ hudText.setString(osstr.str());
+
+ window.draw(hudText);
+ }
+
+ // Display things on screen
+ window.display();
+ }
+
+ // Shut down our thread pool
+ {
+ sf::Lock lock(workQueueMutex);
+ workPending = false;
+ }
+
+ while (!threads.empty())
+ {
+ threads.back()->wait();
+ delete threads.back();
+ threads.pop_back();
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the terrain elevation at the given coordinates.
+///
+////////////////////////////////////////////////////////////
+float getElevation(float x, float y)
+{
+ x = x / resolutionX - 0.5f;
+ y = y / resolutionY - 0.5f;
+
+ float elevation = 0.0f;
+
+ for (int i = 0; i < perlinOctaves; i++)
+ {
+ elevation += stb_perlin_noise3(
+ x * perlinFrequency * std::pow(perlinFrequencyBase, i),
+ y * perlinFrequency * std::pow(perlinFrequencyBase, i),
+ 0, 0, 0, 0
+ ) * std::pow(perlinFrequencyBase, -i);
+ }
+
+ elevation = (elevation + 1.f) / 2.f;
+
+ float distance = 2.0f * std::sqrt(x * x + y * y);
+ elevation = (elevation + heightBase) * (1.0f - edgeFactor * std::pow(distance, edgeDropoffExponent));
+ elevation = std::min(std::max(elevation, 0.0f), 1.0f);
+
+ return elevation;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the terrain moisture at the given coordinates.
+///
+////////////////////////////////////////////////////////////
+float getMoisture(float x, float y)
+{
+ x = x / resolutionX - 0.5f;
+ y = y / resolutionY - 0.5f;
+
+ float moisture = stb_perlin_noise3(
+ x * 4.f + 0.5f,
+ y * 4.f + 0.5f,
+ 0, 0, 0, 0
+ );
+
+ return (moisture + 1.f) / 2.f;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the lowlands terrain color for the given moisture.
+///
+////////////////////////////////////////////////////////////
+sf::Color getLowlandsTerrainColor(float moisture)
+{
+ sf::Color color =
+ moisture < 0.27f ? sf::Color(240, 240, 180) :
+ moisture < 0.3f ? sf::Color(240 - 240 * (moisture - 0.27f) / 0.03f, 240 - 40 * (moisture - 0.27f) / 0.03f, 180 - 180 * (moisture - 0.27f) / 0.03f) :
+ moisture < 0.4f ? sf::Color(0, 200, 0) :
+ moisture < 0.48f ? sf::Color(0, 200 - 40 * (moisture - 0.4f) / 0.08f, 0) :
+ moisture < 0.6f ? sf::Color(0, 160, 0) :
+ moisture < 0.7f ? sf::Color(34 * (moisture - 0.6f) / 0.1f, 160 - 60 * (moisture - 0.6f) / 0.1f, 34 * (moisture - 0.6f) / 0.1f) :
+ sf::Color(34, 100, 34);
+
+ return color;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the highlands terrain color for the given elevation
+/// and moisture.
+///
+////////////////////////////////////////////////////////////
+sf::Color getHighlandsTerrainColor(float elevation, float moisture)
+{
+ sf::Color lowlandsColor = getLowlandsTerrainColor(moisture);
+
+ sf::Color color =
+ moisture < 0.6f ? sf::Color(112, 128, 144) :
+ sf::Color(112 + 110 * (moisture - 0.6f) / 0.4f, 128 + 56 * (moisture - 0.6f) / 0.4f, 144 - 9 * (moisture - 0.6f) / 0.4f);
+
+ float factor = std::min((elevation - 0.4f) / 0.1f, 1.f);
+
+ color.r = lowlandsColor.r * (1.f - factor) + color.r * factor;
+ color.g = lowlandsColor.g * (1.f - factor) + color.g * factor;
+ color.b = lowlandsColor.b * (1.f - factor) + color.b * factor;
+
+ return color;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the snowcap terrain color for the given elevation
+/// and moisture.
+///
+////////////////////////////////////////////////////////////
+sf::Color getSnowcapTerrainColor(float elevation, float moisture)
+{
+ sf::Color highlandsColor = getHighlandsTerrainColor(elevation, moisture);
+
+ sf::Color color = sf::Color::White;
+
+ float factor = std::min((elevation - snowcapHeight) / 0.05f, 1.f);
+
+ color.r = highlandsColor.r * (1.f - factor) + color.r * factor;
+ color.g = highlandsColor.g * (1.f - factor) + color.g * factor;
+ color.b = highlandsColor.b * (1.f - factor) + color.b * factor;
+
+ return color;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the terrain color for the given elevation and
+/// moisture.
+///
+////////////////////////////////////////////////////////////
+sf::Color getTerrainColor(float elevation, float moisture)
+{
+ sf::Color color =
+ elevation < 0.11f ? sf::Color(0, 0, elevation / 0.11f * 74.f + 181.0f) :
+ elevation < 0.14f ? sf::Color(std::pow((elevation - 0.11f) / 0.03f, 0.3f) * 48.f, std::pow((elevation - 0.11f) / 0.03f, 0.3f) * 48.f, 255) :
+ elevation < 0.16f ? sf::Color((elevation - 0.14f) * 128.f / 0.02f + 48.f, (elevation - 0.14f) * 128.f / 0.02f + 48.f, 127.0f + (0.16f - elevation) * 128.f / 0.02f) :
+ elevation < 0.17f ? sf::Color(240, 230, 140) :
+ elevation < 0.4f ? getLowlandsTerrainColor(moisture) :
+ elevation < snowcapHeight ? getHighlandsTerrainColor(elevation, moisture) :
+ getSnowcapTerrainColor(elevation, moisture);
+
+ return color;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Compute a compressed representation of the surface
+/// normal based on the given coordinates, and the elevation
+/// of the 4 adjacent neighbours.
+///
+////////////////////////////////////////////////////////////
+sf::Vector2f computeNormal(int x, int y, float left, float right, float bottom, float top)
+{
+ sf::Vector3f deltaX(1, 0, (std::pow(right, heightFlatten) - std::pow(left, heightFlatten)) * heightFactor);
+ sf::Vector3f deltaY(0, 1, (std::pow(top, heightFlatten) - std::pow(bottom, heightFlatten)) * heightFactor);
+
+ sf::Vector3f crossProduct(
+ deltaX.y * deltaY.z - deltaX.z * deltaY.y,
+ deltaX.z * deltaY.x - deltaX.x * deltaY.z,
+ deltaX.x * deltaY.y - deltaX.y * deltaY.x
+ );
+
+ // Scale cross product to make z component 1.0f so we can drop it
+ crossProduct /= crossProduct.z;
+
+ // Return "compressed" normal
+ return sf::Vector2f(crossProduct.x, crossProduct.y);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Process a terrain generation work item. Use the vector
+/// of vertices as scratch memory and upload the data to
+/// the vertex buffer when done.
+///
+////////////////////////////////////////////////////////////
+void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem)
+{
+ unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
+ unsigned int rowStart = rowBlockSize * workItem.index;
+
+ if (rowStart >= resolutionY)
+ return;
+
+ unsigned int rowEnd = std::min(rowStart + rowBlockSize, resolutionY);
+ unsigned int rowCount = rowEnd - rowStart;
+
+ const float scalingFactorX = static_cast<float>(windowWidth) / static_cast<float>(resolutionX);
+ const float scalingFactorY = static_cast<float>(windowHeight) / static_cast<float>(resolutionY);
+
+ for (unsigned int y = rowStart; y < rowEnd; y++)
+ {
+ for (int x = 0; x < resolutionX; x++)
+ {
+ int arrayIndexBase = ((y - rowStart) * resolutionX + x) * 6;
+
+ // Top left corner (first triangle)
+ if (x > 0)
+ {
+ vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - 6 + 5];
+ }
+ else if (y > rowStart)
+ {
+ vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - resolutionX * 6 + 1];
+ }
+ else
+ {
+ vertices[arrayIndexBase + 0].position = sf::Vector2f(x * scalingFactorX, y * scalingFactorY);
+ vertices[arrayIndexBase + 0].color = getTerrainColor(getElevation(x, y), getMoisture(x, y));
+ vertices[arrayIndexBase + 0].texCoords = computeNormal(x, y, getElevation(x - 1, y), getElevation(x + 1, y), getElevation(x, y + 1), getElevation(x, y - 1));
+ }
+
+ // Bottom left corner (first triangle)
+ if (x > 0)
+ {
+ vertices[arrayIndexBase + 1] = vertices[arrayIndexBase - 6 + 2];
+ }
+ else
+ {
+ vertices[arrayIndexBase + 1].position = sf::Vector2f(x * scalingFactorX, (y + 1) * scalingFactorY);
+ vertices[arrayIndexBase + 1].color = getTerrainColor(getElevation(x, y + 1), getMoisture(x, y + 1));
+ vertices[arrayIndexBase + 1].texCoords = computeNormal(x, y + 1, getElevation(x - 1, y + 1), getElevation(x + 1, y + 1), getElevation(x, y + 2), getElevation(x, y));
+ }
+
+ // Bottom right corner (first triangle)
+ vertices[arrayIndexBase + 2].position = sf::Vector2f((x + 1) * scalingFactorX, (y + 1) * scalingFactorY);
+ vertices[arrayIndexBase + 2].color = getTerrainColor(getElevation(x + 1, y + 1), getMoisture(x + 1, y + 1));
+ vertices[arrayIndexBase + 2].texCoords = computeNormal(x + 1, y + 1, getElevation(x, y + 1), getElevation(x + 2, y + 1), getElevation(x + 1, y + 2), getElevation(x + 1, y));
+
+ // Top left corner (second triangle)
+ vertices[arrayIndexBase + 3] = vertices[arrayIndexBase + 0];
+
+ // Bottom right corner (second triangle)
+ vertices[arrayIndexBase + 4] = vertices[arrayIndexBase + 2];
+
+ // Top right corner (second triangle)
+ if (y > rowStart)
+ {
+ vertices[arrayIndexBase + 5] = vertices[arrayIndexBase - resolutionX * 6 + 2];
+ }
+ else
+ {
+ vertices[arrayIndexBase + 5].position = sf::Vector2f((x + 1) * scalingFactorX, y * scalingFactorY);
+ vertices[arrayIndexBase + 5].color = getTerrainColor(getElevation(x + 1, y), getMoisture(x + 1, y));
+ vertices[arrayIndexBase + 5].texCoords = computeNormal(x + 1, y, getElevation(x, y), getElevation(x + 2, y), getElevation(x + 1, y + 1), getElevation(x + 1, y - 1));
+ }
+ }
+ }
+
+ // Copy the resulting geometry from our thread-local buffer into the target buffer
+ std::memcpy(workItem.targetBuffer + (resolutionX * rowStart * 6), &vertices[0], sizeof(sf::Vertex) * resolutionX * rowCount * 6);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Worker thread entry point. We use a thread pool to avoid
+/// the heavy cost of constantly recreating and starting
+/// new threads whenever we need to regenerate the terrain.
+///
+////////////////////////////////////////////////////////////
+void threadFunction()
+{
+ unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
+
+ std::vector<sf::Vertex> vertices(resolutionX * rowBlockSize * 6);
+
+ WorkItem workItem = {0, 0};
+
+ // Loop until the application exits
+ for (;;)
+ {
+ workItem.targetBuffer = 0;
+
+ // Check if there are new work items in the queue
+ {
+ sf::Lock lock(workQueueMutex);
+
+ if (!workPending)
+ return;
+
+ if (!workQueue.empty())
+ {
+ workItem = workQueue.front();
+ workQueue.pop_front();
+ }
+ }
+
+ // If we didn't receive a new work item, keep looping
+ if (!workItem.targetBuffer)
+ {
+ sf::sleep(sf::milliseconds(10));
+
+ continue;
+ }
+
+ processWorkItem(vertices, workItem);
+
+ {
+ sf::Lock lock(workQueueMutex);
+
+ --pendingWorkCount;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Terrain generation entry point. This queues up the
+/// generation work items which the worker threads dequeue
+/// and process.
+///
+////////////////////////////////////////////////////////////
+void generateTerrain(sf::Vertex* buffer)
+{
+ bufferUploadPending = true;
+
+ // Make sure the work queue is empty before queuing new work
+ for (;;)
+ {
+ {
+ sf::Lock lock(workQueueMutex);
+
+ if (workQueue.empty())
+ break;
+ }
+
+ sf::sleep(sf::milliseconds(10));
+ }
+
+ // Queue all the new work items
+ {
+ sf::Lock lock(workQueueMutex);
+
+ for (unsigned int i = 0; i < blockCount; i++)
+ {
+ WorkItem workItem = {buffer, i};
+ workQueue.push_back(workItem);
+ }
+
+ pendingWorkCount = blockCount;
+ }
+}
diff --git a/examples/island/resources/sansation.ttf b/examples/island/resources/sansation.ttf
new file mode 100644
index 0000000..d85fbc8
--- /dev/null
+++ b/examples/island/resources/sansation.ttf
Binary files differ
diff --git a/examples/island/resources/terrain.frag b/examples/island/resources/terrain.frag
new file mode 100644
index 0000000..ae18187
--- /dev/null
+++ b/examples/island/resources/terrain.frag
@@ -0,0 +1,11 @@
+varying vec3 normal;
+uniform float lightFactor;
+
+void main()
+{
+ vec3 lightPosition = vec3(-1.0, 1.0, 1.0);
+ vec3 eyePosition = vec3(0.0, 0.0, 1.0);
+ vec3 halfVector = normalize(lightPosition + eyePosition);
+ float intensity = lightFactor + (1.0 - lightFactor) * dot(normalize(normal), normalize(halfVector));
+ gl_FragColor = gl_Color * vec4(intensity, intensity, intensity, 1.0);
+}
diff --git a/examples/island/resources/terrain.vert b/examples/island/resources/terrain.vert
new file mode 100644
index 0000000..a06996d
--- /dev/null
+++ b/examples/island/resources/terrain.vert
@@ -0,0 +1,8 @@
+varying vec3 normal;
+
+void main()
+{
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_FrontColor = gl_Color;
+ normal = vec3(gl_MultiTexCoord0.xy, 1.0);
+}
diff --git a/examples/island/stb_perlin.h b/examples/island/stb_perlin.h
new file mode 100644
index 0000000..5d76222
--- /dev/null
+++ b/examples/island/stb_perlin.h
@@ -0,0 +1,316 @@
+// stb_perlin.h - v0.3 - perlin noise
+// public domain single-file C implementation by Sean Barrett
+//
+// LICENSE
+//
+// See end of file.
+//
+//
+// to create the implementation,
+// #define STB_PERLIN_IMPLEMENTATION
+// in *one* C/CPP file that includes this file.
+//
+//
+// Documentation:
+//
+// float stb_perlin_noise3( float x,
+// float y,
+// float z,
+// int x_wrap=0,
+// int y_wrap=0,
+// int z_wrap=0)
+//
+// This function computes a random value at the coordinate (x,y,z).
+// Adjacent random values are continuous but the noise fluctuates
+// its randomness with period 1, i.e. takes on wholly unrelated values
+// at integer points. Specifically, this implements Ken Perlin's
+// revised noise function from 2002.
+//
+// The "wrap" parameters can be used to create wraparound noise that
+// wraps at powers of two. The numbers MUST be powers of two. Specify
+// 0 to mean "don't care". (The noise always wraps every 256 due
+// details of the implementation, even if you ask for larger or no
+// wrapping.)
+//
+// Fractal Noise:
+//
+// Three common fractal noise functions are included, which produce
+// a wide variety of nice effects depending on the parameters
+// provided. Note that each function will call stb_perlin_noise3
+// 'octaves' times, so this parameter will affect runtime.
+//
+// float stb_perlin_ridge_noise3(float x, float y, float z,
+// float lacunarity, float gain, float offset, int octaves,
+// int x_wrap, int y_wrap, int z_wrap);
+//
+// float stb_perlin_fbm_noise3(float x, float y, float z,
+// float lacunarity, float gain, int octaves,
+// int x_wrap, int y_wrap, int z_wrap);
+//
+// float stb_perlin_turbulence_noise3(float x, float y, float z,
+// float lacunarity, float gain,int octaves,
+// int x_wrap, int y_wrap, int z_wrap);
+//
+// Typical values to start playing with:
+// octaves = 6 -- number of "octaves" of noise3() to sum
+// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output)
+// gain = 0.5 -- relative weighting applied to each successive octave
+// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure
+//
+//
+// Contributors:
+// Jack Mott - additional noise functions
+//
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef STB_PERLIN_IMPLEMENTATION
+
+// not same permutation table as Perlin's reference to avoid copyright issues;
+// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
+// @OPTIMIZE: should this be unsigned char instead of int for cache?
+static unsigned char stb__perlin_randtab[512] =
+{
+ 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
+ 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
+ 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
+ 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
+ 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
+ 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
+ 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
+ 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
+ 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
+ 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
+ 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
+ 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
+ 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
+ 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
+ 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
+ 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
+
+ // and a second copy so we don't need an extra mask or static initializer
+ 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
+ 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
+ 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
+ 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
+ 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
+ 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
+ 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
+ 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
+ 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
+ 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
+ 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
+ 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
+ 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
+ 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
+ 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
+ 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
+};
+
+static float stb__perlin_lerp(float a, float b, float t)
+{
+ return a + (b-a) * t;
+}
+
+static int stb__perlin_fastfloor(float a)
+{
+ int ai = (int) a;
+ return (a < ai) ? ai-1 : ai;
+}
+
+// different grad function from Perlin's, but easy to modify to match reference
+static float stb__perlin_grad(int hash, float x, float y, float z)
+{
+ static float basis[12][4] =
+ {
+ { 1, 1, 0 },
+ { -1, 1, 0 },
+ { 1,-1, 0 },
+ { -1,-1, 0 },
+ { 1, 0, 1 },
+ { -1, 0, 1 },
+ { 1, 0,-1 },
+ { -1, 0,-1 },
+ { 0, 1, 1 },
+ { 0,-1, 1 },
+ { 0, 1,-1 },
+ { 0,-1,-1 },
+ };
+
+ // perlin's gradient has 12 cases so some get used 1/16th of the time
+ // and some 2/16ths. We reduce bias by changing those fractions
+ // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight.
+ static unsigned char indices[64] =
+ {
+ 0,1,2,3,4,5,6,7,8,9,10,11,
+ 0,9,1,11,
+ 0,1,2,3,4,5,6,7,8,9,10,11,
+ 0,1,2,3,4,5,6,7,8,9,10,11,
+ 0,1,2,3,4,5,6,7,8,9,10,11,
+ 0,1,2,3,4,5,6,7,8,9,10,11,
+ };
+
+ // if you use reference permutation table, change 63 below to 15 to match reference
+ // (this is why the ordering of the table above is funky)
+ float *grad = basis[indices[hash & 63]];
+ return grad[0]*x + grad[1]*y + grad[2]*z;
+}
+
+float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap)
+{
+ float u,v,w;
+ float n000,n001,n010,n011,n100,n101,n110,n111;
+ float n00,n01,n10,n11;
+ float n0,n1;
+
+ unsigned int x_mask = (x_wrap-1) & 255;
+ unsigned int y_mask = (y_wrap-1) & 255;
+ unsigned int z_mask = (z_wrap-1) & 255;
+ int px = stb__perlin_fastfloor(x);
+ int py = stb__perlin_fastfloor(y);
+ int pz = stb__perlin_fastfloor(z);
+ int x0 = px & x_mask, x1 = (px+1) & x_mask;
+ int y0 = py & y_mask, y1 = (py+1) & y_mask;
+ int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
+ int r0,r1, r00,r01,r10,r11;
+
+ #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
+
+ x -= px; u = stb__perlin_ease(x);
+ y -= py; v = stb__perlin_ease(y);
+ z -= pz; w = stb__perlin_ease(z);
+
+ r0 = stb__perlin_randtab[x0];
+ r1 = stb__perlin_randtab[x1];
+
+ r00 = stb__perlin_randtab[r0+y0];
+ r01 = stb__perlin_randtab[r0+y1];
+ r10 = stb__perlin_randtab[r1+y0];
+ r11 = stb__perlin_randtab[r1+y1];
+
+ n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z );
+ n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 );
+ n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z );
+ n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 );
+ n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z );
+ n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 );
+ n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z );
+ n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 );
+
+ n00 = stb__perlin_lerp(n000,n001,w);
+ n01 = stb__perlin_lerp(n010,n011,w);
+ n10 = stb__perlin_lerp(n100,n101,w);
+ n11 = stb__perlin_lerp(n110,n111,w);
+
+ n0 = stb__perlin_lerp(n00,n01,v);
+ n1 = stb__perlin_lerp(n10,n11,v);
+
+ return stb__perlin_lerp(n0,n1,u);
+}
+
+float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+ int i;
+ float frequency = 1.0f;
+ float prev = 1.0f;
+ float amplitude = 0.5f;
+ float sum = 0.0f;
+
+ for (i = 0; i < octaves; i++) {
+ float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap));
+ r = r<0 ? -r : r; // fabs()
+ r = offset - r;
+ r = r*r;
+ sum += r*amplitude*prev;
+ prev = r;
+ frequency *= lacunarity;
+ amplitude *= gain;
+ }
+ return sum;
+}
+
+float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+ int i;
+ float frequency = 1.0f;
+ float amplitude = 1.0f;
+ float sum = 0.0f;
+
+ for (i = 0; i < octaves; i++) {
+ sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
+ frequency *= lacunarity;
+ amplitude *= gain;
+ }
+ return sum;
+}
+
+float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+ int i;
+ float frequency = 1.0f;
+ float amplitude = 1.0f;
+ float sum = 0.0f;
+
+ for (i = 0; i < octaves; i++) {
+ float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
+ r = r<0 ? -r : r; // fabs()
+ sum += r;
+ frequency *= lacunarity;
+ amplitude *= gain;
+ }
+ return sum;
+}
+
+#endif // STB_PERLIN_IMPLEMENTATION
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/examples/joystick/CMakeLists.txt b/examples/joystick/CMakeLists.txt
new file mode 100644
index 0000000..f04dc7f
--- /dev/null
+++ b/examples/joystick/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/joystick)
+
+# all source files
+set(SRC ${SRCROOT}/Joystick.cpp)
+
+# define the joystick target
+sfml_add_example(joystick GUI_APP
+ SOURCES ${SRC}
+ DEPENDS sfml-graphics sfml-window sfml-system
+ RESOURCES_DIR resources)
diff --git a/examples/joystick/Joystick.cpp b/examples/joystick/Joystick.cpp
new file mode 100644
index 0000000..0ff7cf9
--- /dev/null
+++ b/examples/joystick/Joystick.cpp
@@ -0,0 +1,238 @@
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Graphics.hpp>
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <map>
+
+
+namespace
+{
+ struct JoystickObject
+ {
+ sf::Text label;
+ sf::Text value;
+ };
+
+ typedef std::map<std::string, JoystickObject> Texts;
+ Texts texts;
+ std::ostringstream sstr;
+ float threshold = 0.1f;
+
+ // Axes labels in as C strings
+ const char* axislabels[] = {"X", "Y", "Z", "R", "U", "V", "PovX", "PovY"};
+
+ // Helper to set text entries to a specified value
+ template<typename T>
+ void set(const char* label, const T& value)
+ {
+ sstr.str("");
+ sstr << value;
+ texts[label].value.setString(sstr.str());
+ }
+
+ // Update joystick identification
+ void updateIdentification(unsigned int index)
+ {
+ sstr.str("");
+ sstr << "Joystick " << index << ":";
+ texts["ID"].label.setString(sstr.str());
+ texts["ID"].value.setString(sf::Joystick::getIdentification(index).name);
+ }
+
+ // Update joystick axes
+ void updateAxes(unsigned int index)
+ {
+ for (unsigned int j = 0; j < sf::Joystick::AxisCount; ++j)
+ {
+ if (sf::Joystick::hasAxis(index, static_cast<sf::Joystick::Axis>(j)))
+ set(axislabels[j], sf::Joystick::getAxisPosition(index, static_cast<sf::Joystick::Axis>(j)));
+ }
+ }
+
+ // Update joystick buttons
+ void updateButtons(unsigned int index)
+ {
+ for (unsigned int j = 0; j < sf::Joystick::getButtonCount(index); ++j)
+ {
+ sstr.str("");
+ sstr << "Button " << j;
+
+ set(sstr.str().c_str(), sf::Joystick::isButtonPressed(index, j));
+ }
+ }
+
+ // Helper to update displayed joystick values
+ void updateValues(unsigned int index)
+ {
+ if (sf::Joystick::isConnected(index)) {
+ // Update the label-value sf::Text objects based on the current joystick state
+ updateIdentification(index);
+ updateAxes(index);
+ updateButtons(index);
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Entry point of application
+///
+/// \return Application exit code
+///
+////////////////////////////////////////////////////////////
+int main()
+{
+ // Create the window of the application
+ sf::RenderWindow window(sf::VideoMode(400, 680), "Joystick", sf::Style::Close);
+ window.setVerticalSyncEnabled(true);
+
+ // Load the text font
+ sf::Font font;
+ if (!font.loadFromFile("resources/sansation.ttf"))
+ return EXIT_FAILURE;
+
+ // Set up our string conversion parameters
+ sstr.precision(2);
+ sstr.setf(std::ios::fixed | std::ios::boolalpha);
+
+ // Set up our joystick identification sf::Text objects
+ texts["ID"].label.setPosition(5.f, 5.f);
+ texts["ID"].value.setPosition(80.f, 5.f);
+
+ texts["ID"].label.setString("<Not Connected>");
+ texts["ID"].value.setString("");
+
+ // Set up our threshold sf::Text objects
+ sstr.str("");
+ sstr << threshold << " (Change with up/down arrow keys)";
+
+ texts["Threshold"].label.setPosition(5.f, 5.f + 2 * font.getLineSpacing(14));
+ texts["Threshold"].value.setPosition(80.f, 5.f + 2 * font.getLineSpacing(14));
+
+ texts["Threshold"].label.setString("Threshold:");
+ texts["Threshold"].value.setString(sstr.str());
+
+ // Set up our label-value sf::Text objects
+ for (unsigned int i = 0; i < sf::Joystick::AxisCount; ++i)
+ {
+ JoystickObject& object = texts[axislabels[i]];
+
+ object.label.setPosition(5.f, 5.f + ((i + 4) * font.getLineSpacing(14)));
+ object.label.setString(std::string(axislabels[i]) + ":");
+
+ object.value.setPosition(80.f, 5.f + ((i + 4) * font.getLineSpacing(14)));
+ object.value.setString("N/A");
+ }
+
+ for (unsigned int i = 0; i < sf::Joystick::ButtonCount; ++i)
+ {
+ sstr.str("");
+ sstr << "Button " << i;
+ JoystickObject& object = texts[sstr.str()];
+
+ object.label.setPosition(5.f, 5.f + ((sf::Joystick::AxisCount + i + 4) * font.getLineSpacing(14)));
+ object.label.setString(sstr.str() + ":");
+
+ object.value.setPosition(80.f, 5.f + ((sf::Joystick::AxisCount + i + 4) * font.getLineSpacing(14)));
+ object.value.setString("N/A");
+ }
+
+ for (Texts::iterator it = texts.begin(); it != texts.end(); ++it)
+ {
+ it->second.label.setFont(font);
+ it->second.label.setCharacterSize(14);
+ it->second.label.setFillColor(sf::Color::White);
+
+ it->second.value.setFont(font);
+ it->second.value.setCharacterSize(14);
+ it->second.value.setFillColor(sf::Color::White);
+ }
+
+ // Update initially displayed joystick values if a joystick is already connected on startup
+ for (unsigned int i = 0; i < sf::Joystick::Count; ++i)
+ {
+ if (sf::Joystick::isConnected(i))
+ {
+ updateValues(i);
+ break;
+ }
+ }
+
+ while (window.isOpen())
+ {
+ // Handle events
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ // Window closed or escape key pressed: exit
+ if ((event.type == sf::Event::Closed) ||
+ ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
+ {
+ window.close();
+ break;
+ }
+ else if ((event.type == sf::Event::JoystickButtonPressed) ||
+ (event.type == sf::Event::JoystickButtonReleased) ||
+ (event.type == sf::Event::JoystickMoved) ||
+ (event.type == sf::Event::JoystickConnected))
+ {
+ // Update displayed joystick values
+ updateValues(event.joystickConnect.joystickId);
+ }
+ else if (event.type == sf::Event::JoystickDisconnected)
+ {
+ // Reset displayed joystick values to empty
+ for (Texts::iterator it = texts.begin(); it != texts.end(); ++it)
+ it->second.value.setString("N/A");
+
+ texts["ID"].label.setString("<Not Connected>");
+ texts["ID"].value.setString("");
+
+ sstr.str("");
+ sstr << threshold << " (Change with up/down arrow keys)";
+
+ texts["Threshold"].value.setString(sstr.str());
+ }
+ }
+
+ // Update threshold if the user wants to change it
+ float newThreshold = threshold;
+
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
+ newThreshold += 0.1f;
+
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
+ newThreshold -= 0.1f;
+
+ newThreshold = std::min(std::max(newThreshold, 0.1f), 100.0f);
+
+ if (newThreshold != threshold)
+ {
+ threshold = newThreshold;
+ window.setJoystickThreshold(threshold);
+
+ sstr.str("");
+ sstr << threshold << " (Change with up/down arrow keys)";
+
+ texts["Threshold"].value.setString(sstr.str());
+ }
+
+ // Clear the window
+ window.clear();
+
+ // Draw the label-value sf::Text objects
+ for (Texts::const_iterator it = texts.begin(); it != texts.end(); ++it)
+ {
+ window.draw(it->second.label);
+ window.draw(it->second.value);
+ }
+
+ // Display things on screen
+ window.display();
+ }
+}
diff --git a/examples/joystick/resources/sansation.ttf b/examples/joystick/resources/sansation.ttf
new file mode 100644
index 0000000..d85fbc8
--- /dev/null
+++ b/examples/joystick/resources/sansation.ttf
Binary files differ
diff --git a/examples/opengl/CMakeLists.txt b/examples/opengl/CMakeLists.txt
index 3bac2b9..9b8ad49 100644
--- a/examples/opengl/CMakeLists.txt
+++ b/examples/opengl/CMakeLists.txt
@@ -4,12 +4,8 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/opengl)
# all source files
set(SRC ${SRCROOT}/OpenGL.cpp)
-# find OpenGL
-find_package(OpenGL REQUIRED)
-include_directories(${OPENGL_INCLUDE_DIR})
-set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES})
-
# define the opengl target
sfml_add_example(opengl GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-graphics sfml-window sfml-system ${ADDITIONAL_LIBRARIES})
+ DEPENDS sfml-graphics OpenGL
+ RESOURCES_DIR resources)
diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp
index 20af113..f2260d6 100644
--- a/examples/opengl/OpenGL.cpp
+++ b/examples/opengl/OpenGL.cpp
@@ -63,6 +63,9 @@ int main()
// mipmapping is purely optional in this example
texture.generateMipmap();
+ // Make the window the active window for OpenGL calls
+ window.setActive(true);
+
// Enable Z-buffer read and write
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
@@ -141,6 +144,9 @@ int main()
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
+ // Make the window no longer the active window for OpenGL calls
+ window.setActive(false);
+
// Create a clock for measuring the time elapsed
sf::Clock clock;
@@ -169,7 +175,7 @@ int main()
}
// Return key: toggle mipmapping
- if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Return))
+ if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Enter))
{
if (mipmapEnabled)
{
@@ -196,7 +202,15 @@ int main()
// Adjust the viewport when the window is resized
if (event.type == sf::Event::Resized)
+ {
+ // Make the window the active window for OpenGL calls
+ window.setActive(true);
+
glViewport(0, 0, event.size.width, event.size.height);
+
+ // Make the window no longer the active window for OpenGL calls
+ window.setActive(false);
+ }
}
// Draw the background
@@ -204,6 +218,9 @@ int main()
window.draw(background);
window.popGLStates();
+ // Make the window the active window for OpenGL calls
+ window.setActive(true);
+
// Clear the depth buffer
glClear(GL_DEPTH_BUFFER_BIT);
@@ -222,6 +239,9 @@ int main()
// Draw the cube
glDrawArrays(GL_TRIANGLES, 0, 36);
+ // Make the window no longer the active window for OpenGL calls
+ window.setActive(false);
+
// Draw some text on top of our OpenGL object
window.pushGLStates();
window.draw(text);
diff --git a/examples/pong/CMakeLists.txt b/examples/pong/CMakeLists.txt
index 8b1c4bc..a20f3b1 100644
--- a/examples/pong/CMakeLists.txt
+++ b/examples/pong/CMakeLists.txt
@@ -7,4 +7,5 @@ set(SRC ${SRCROOT}/Pong.cpp)
# define the pong target
sfml_add_example(pong GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-audio sfml-graphics sfml-window sfml-system)
+ DEPENDS sfml-audio sfml-graphics
+ RESOURCES_DIR resources)
diff --git a/examples/shader/CMakeLists.txt b/examples/shader/CMakeLists.txt
index eb908b2..600cb4d 100644
--- a/examples/shader/CMakeLists.txt
+++ b/examples/shader/CMakeLists.txt
@@ -9,4 +9,5 @@ set(SRC
# define the shader target
sfml_add_example(shader GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-graphics sfml-window sfml-system)
+ DEPENDS sfml-graphics
+ RESOURCES_DIR resources)
diff --git a/examples/sockets/CMakeLists.txt b/examples/sockets/CMakeLists.txt
index b9f4b64..eebc91d 100644
--- a/examples/sockets/CMakeLists.txt
+++ b/examples/sockets/CMakeLists.txt
@@ -9,4 +9,4 @@ set(SRC ${SRCROOT}/Sockets.cpp
# define the sockets target
sfml_add_example(sockets
SOURCES ${SRC}
- DEPENDS sfml-network sfml-system)
+ DEPENDS sfml-network)
diff --git a/examples/sound/CMakeLists.txt b/examples/sound/CMakeLists.txt
index 0108577..d3875a6 100644
--- a/examples/sound/CMakeLists.txt
+++ b/examples/sound/CMakeLists.txt
@@ -7,4 +7,5 @@ set(SRC ${SRCROOT}/Sound.cpp)
# define the sound target
sfml_add_example(sound
SOURCES ${SRC}
- DEPENDS sfml-audio sfml-system)
+ DEPENDS sfml-audio
+ RESOURCES_DIR resources)
diff --git a/examples/sound_capture/CMakeLists.txt b/examples/sound_capture/CMakeLists.txt
index e62b3b3..e2c457f 100644
--- a/examples/sound_capture/CMakeLists.txt
+++ b/examples/sound_capture/CMakeLists.txt
@@ -7,4 +7,4 @@ set(SRC ${SRCROOT}/SoundCapture.cpp)
# define the sound-capture target
sfml_add_example(sound-capture
SOURCES ${SRC}
- DEPENDS sfml-audio sfml-system)
+ DEPENDS sfml-audio)
diff --git a/examples/voip/CMakeLists.txt b/examples/voip/CMakeLists.txt
index 0e4e710..66bc074 100644
--- a/examples/voip/CMakeLists.txt
+++ b/examples/voip/CMakeLists.txt
@@ -9,4 +9,4 @@ set(SRC ${SRCROOT}/VoIP.cpp
# define the voip target
sfml_add_example(voip
SOURCES ${SRC}
- DEPENDS sfml-audio sfml-network sfml-system)
+ DEPENDS sfml-audio sfml-network)
diff --git a/examples/win32/CMakeLists.txt b/examples/win32/CMakeLists.txt
index c0bea6e..bd952c5 100644
--- a/examples/win32/CMakeLists.txt
+++ b/examples/win32/CMakeLists.txt
@@ -7,4 +7,5 @@ set(SRC ${SRCROOT}/Win32.cpp)
# define the win32 target
sfml_add_example(win32 GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-graphics sfml-window sfml-system)
+ DEPENDS sfml-graphics
+ RESOURCES_DIR resources)
diff --git a/examples/window/CMakeLists.txt b/examples/window/CMakeLists.txt
index 2ce61a0..b106c04 100644
--- a/examples/window/CMakeLists.txt
+++ b/examples/window/CMakeLists.txt
@@ -4,12 +4,7 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/window)
# all source files
set(SRC ${SRCROOT}/Window.cpp)
-# find OpenGL
-find_package(OpenGL REQUIRED)
-include_directories(${OPENGL_INCLUDE_DIR})
-set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES})
-
# define the window target
sfml_add_example(window GUI_APP
SOURCES ${SRC}
- DEPENDS sfml-window sfml-system ${ADDITIONAL_LIBRARIES})
+ DEPENDS sfml-window OpenGL)
diff --git a/extlibs/Android.mk b/extlibs/Android.mk
index 0960e3e..26d966b 100644
--- a/extlibs/Android.mk
+++ b/extlibs/Android.mk
@@ -7,12 +7,6 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
-LOCAL_MODULE := jpeg
-LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libjpeg.a
-LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
LOCAL_MODULE := openal
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libopenal.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
diff --git a/extlibs/headers/stb_image/stb_image.h b/extlibs/headers/stb_image/stb_image.h
index c3945c2..a056138 100644
--- a/extlibs/headers/stb_image/stb_image.h
+++ b/extlibs/headers/stb_image/stb_image.h
@@ -1,4 +1,4 @@
-/* stb_image - v2.02 - public domain image loader - http://nothings.org/stb_image.h
+/* stb_image - v2.16 - public domain image loader - http://nothings.org/stb_image.h
no warranty implied; use at your own risk
Do this:
@@ -21,17 +21,20 @@
avoid problematic images and only need the trivial interface
JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
- PNG 1/2/4/8-bit-per-channel (16 bpc not supported)
+ PNG 1/2/4/8/16-bit-per-channel
TGA (not sure what subset, if a subset)
BMP non-1bpp, non-RLE
- PSD (composited view only, no extra channels)
+ PSD (composited view only, no extra channels, 8/16 bit-per-channel)
GIF (*comp always reports as 4-channel)
HDR (radiance rgbE format)
PIC (Softimage PIC)
PNM (PPM and PGM binary only)
+ Animated GIF still needs a proper API, but here's one way to do it:
+ http://gist.github.com/urraka/685d9a6340b26b830d49
+
- decode from memory or through FILE (define STBI_NO_STDIO to remove code)
- decode from arbitrary I/O callbacks
- SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
@@ -39,169 +42,61 @@
Full documentation under "DOCUMENTATION" below.
- Revision 2.00 release notes:
-
- - Progressive JPEG is now supported.
-
- - PPM and PGM binary formats are now supported, thanks to Ken Miller.
-
- - x86 platforms now make use of SSE2 SIMD instructions for
- JPEG decoding, and ARM platforms can use NEON SIMD if requested.
- This work was done by Fabian "ryg" Giesen. SSE2 is used by
- default, but NEON must be enabled explicitly; see docs.
-
- With other JPEG optimizations included in this version, we see
- 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup
- on a JPEG on an ARM machine, relative to previous versions of this
- library. The same results will not obtain for all JPGs and for all
- x86/ARM machines. (Note that progressive JPEGs are significantly
- slower to decode than regular JPEGs.) This doesn't mean that this
- is the fastest JPEG decoder in the land; rather, it brings it
- closer to parity with standard libraries. If you want the fastest
- decode, look elsewhere. (See "Philosophy" section of docs below.)
-
- See final bullet items below for more info on SIMD.
-
- - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing
- the memory allocator. Unlike other STBI libraries, these macros don't
- support a context parameter, so if you need to pass a context in to
- the allocator, you'll have to store it in a global or a thread-local
- variable.
-
- - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and
- STBI_NO_LINEAR.
- STBI_NO_HDR: suppress implementation of .hdr reader format
- STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API
-
- - You can suppress implementation of any of the decoders to reduce
- your code footprint by #defining one or more of the following
- symbols before creating the implementation.
-
- STBI_NO_JPEG
- STBI_NO_PNG
- STBI_NO_BMP
- STBI_NO_PSD
- STBI_NO_TGA
- STBI_NO_GIF
- STBI_NO_HDR
- STBI_NO_PIC
- STBI_NO_PNM (.ppm and .pgm)
-
- - You can request *only* certain decoders and suppress all other ones
- (this will be more forward-compatible, as addition of new decoders
- doesn't require you to disable them explicitly):
-
- STBI_ONLY_JPEG
- STBI_ONLY_PNG
- STBI_ONLY_BMP
- STBI_ONLY_PSD
- STBI_ONLY_TGA
- STBI_ONLY_GIF
- STBI_ONLY_HDR
- STBI_ONLY_PIC
- STBI_ONLY_PNM (.ppm and .pgm)
-
- Note that you can define multiples of these, and you will get all
- of them ("only x" and "only y" is interpreted to mean "only x&y").
-
- - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
- want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
-
- - Compilation of all SIMD code can be suppressed with
- #define STBI_NO_SIMD
- It should not be necessary to disable SIMD unless you have issues
- compiling (e.g. using an x86 compiler which doesn't support SSE
- intrinsics or that doesn't support the method used to detect
- SSE2 support at run-time), and even those can be reported as
- bugs so I can refine the built-in compile-time checking to be
- smarter.
-
- - The old STBI_SIMD system which allowed installing a user-defined
- IDCT etc. has been removed. If you need this, don't upgrade. My
- assumption is that almost nobody was doing this, and those who
- were will find the built-in SIMD more satisfactory anyway.
-
- - RGB values computed for JPEG images are slightly different from
- previous versions of stb_image. (This is due to using less
- integer precision in SIMD.) The C code has been adjusted so
- that the same RGB values will be computed regardless of whether
- SIMD support is available, so your app should always produce
- consistent results. But these results are slightly different from
- previous versions. (Specifically, about 3% of available YCbCr values
- will compute different RGB results from pre-1.49 versions by +-1;
- most of the deviating values are one smaller in the G channel.)
-
- - If you must produce consistent results with previous versions of
- stb_image, #define STBI_JPEG_OLD and you will get the same results
- you used to; however, you will not get the SIMD speedups for
- the YCbCr-to-RGB conversion step (although you should still see
- significant JPEG speedup from the other changes).
-
- Please note that STBI_JPEG_OLD is a temporary feature; it will be
- removed in future versions of the library. It is only intended for
- near-term back-compatibility use.
-
-
- Latest revision history:
- 2.02 (2015-01-19) fix incorrect assert, fix warning
- 2.01 (2015-01-17) fix various warnings
- 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
- 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD
- progressive JPEG
- PGM/PPM support
- STBI_MALLOC,STBI_REALLOC,STBI_FREE
- STBI_NO_*, STBI_ONLY_*
- GIF bugfix
- 1.48 (2014-12-14) fix incorrectly-named assert()
- 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
- optimize PNG
- fix bug in interlaced PNG with user-specified channel count
- 1.46 (2014-08-26) fix broken tRNS chunk in non-paletted PNG
- 1.45 (2014-08-16) workaround MSVC-ARM internal compiler error by wrapping malloc
+LICENSE
+
+ See end of file for license information.
+
+RECENT REVISION HISTORY:
+
+ 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+ 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+ 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+ 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+ RGB-format JPEG; remove white matting in PSD;
+ allocate large structures on the stack;
+ correct channel count for PNG & BMP
+ 2.10 (2016-01-22) avoid warning introduced in 2.09
+ 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
See end of file for full revision history.
============================ Contributors =========================
- Image formats Bug fixes & warning fixes
- Sean Barrett (jpeg, png, bmp) Marc LeBlanc
- Nicolas Schulz (hdr, psd) Christpher Lloyd
- Jonathan Dummer (tga) Dave Moore
- Jean-Marc Lienher (gif) Won Chun
- Tom Seddon (pic) the Horde3D community
- Thatcher Ulrich (psd) Janez Zemva
- Ken Miller (pgm, ppm) Jonathan Blow
- Laurent Gomila
- Aruelien Pocheville
- Extensions, features Ryamond Barbiero
- Jetro Lauha (stbi_info) David Woo
- Martin "SpartanJ" Golini (stbi_info) Martin Golini
- James "moose2000" Brown (iPhone PNG) Roy Eltham
- Ben "Disch" Wenger (io callbacks) Luke Graham
- Omar Cornut (1/2/4-bit PNG) Thomas Ruf
- John Bartholomew
- Ken Hamada
- Optimizations & bugfixes Cort Stratton
- Fabian "ryg" Giesen Blazej Dariusz Roszkowski
- Arseny Kapoulkine Thibault Reuille
- Paul Du Bois
- Guillaume George
- If your name should be here but Jerry Jansson
- isn't, let Sean know. Hayaki Saito
- Johan Duparc
- Ronny Chevalier
- Michal Cichon
- Tero Hanninen
- Sergio Gonzalez
- Cass Everitt
- Engin Manap
-
-License:
- This software is in the public domain. Where that dedication is not
- recognized, you are granted a perpetual, irrevocable license to copy
- and modify this file however you want.
-
+ Image formats Extensions, features
+ Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
+ Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
+ Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
+ Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
+ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
+ Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
+ Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
+ github:urraka (animated gif) Junggon Kim (PNM comments)
+ Daniel Gibson (16-bit TGA)
+ socks-the-fox (16-bit PNG)
+ Jeremy Sawicki (handle all ImageNet JPGs)
+ Optimizations & bugfixes
+ Fabian "ryg" Giesen
+ Arseny Kapoulkine
+ John-Mark Allen
+
+ Bug & warning fixes
+ Marc LeBlanc David Woo Guillaume George Martins Mozeiko
+ Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
+ Dave Moore Roy Eltham Hayaki Saito Nathan Reed
+ Won Chun Luke Graham Johan Duparc Nick Verigakis
+ the Horde3D community Thomas Ruf Ronny Chevalier Baldur Karlsson
+ Janez Zemva John Bartholomew Michal Cichon github:rlyeh
+ Jonathan Blow Ken Hamada Tero Hanninen github:romigrou
+ Laurent Gomila Cort Stratton Sergio Gonzalez github:svdijk
+ Aruelien Pocheville Thibault Reuille Cass Everitt github:snagar
+ Ryamond Barbiero Paul Du Bois Engin Manap github:Zelex
+ Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210
+ Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw
+ Blazej Dariusz Roszkowski Gregory Mullen github:phprus
+ Christian Floisand Kevin Schmidt github:poppolopoppo
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
@@ -226,10 +121,10 @@ License:
// stbi_image_free(data)
//
// Standard parameters:
-// int *x -- outputs image width in pixels
-// int *y -- outputs image height in pixels
-// int *comp -- outputs # of image components in image file
-// int req_comp -- if non-zero, # of image components requested in result
+// int *x -- outputs image width in pixels
+// int *y -- outputs image height in pixels
+// int *channels_in_file -- outputs # of image components in image file
+// int desired_channels -- if non-zero, # of image components requested in result
//
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data, or NULL on an allocation failure or if the image is
@@ -237,11 +132,12 @@ License:
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
-// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
-// If req_comp is non-zero, *comp has the number of components that _would_
-// have been output otherwise. E.g. if you set req_comp to 4, you will always
-// get RGBA output, but you can check *comp to see if it's trivially opaque
-// because e.g. there were only 3 channels in the source image.
+// components N is 'desired_channels' if desired_channels is non-zero, or
+// *channels_in_file otherwise. If desired_channels is non-zero,
+// *channels_in_file has the number of components that _would_ have been
+// output otherwise. E.g. if you set desired_channels to 4, you will always
+// get RGBA output, but you can check *channels_in_file to see if it's trivially
+// opaque because e.g. there were only 3 channels in the source image.
//
// An output image with N components has the following components interleaved
// in this order in each pixel:
@@ -253,10 +149,10 @@ License:
// 4 red, green, blue, alpha
//
// If image loading fails for any reason, the return value will be NULL,
-// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
-// can be queried for an extremely brief, end-user unfriendly explanation
-// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
-// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
+// and *x, *y, *channels_in_file will be unchanged. The function
+// stbi_failure_reason() can be queried for an extremely brief, end-user
+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
// more user-friendly ones.
//
// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
@@ -275,13 +171,13 @@ License:
// and for best performance I may provide less-easy-to-use APIs that give higher
// performance, in addition to the easy to use ones. Nevertheless, it's important
// to keep in mind that from the standpoint of you, a client of this library,
-// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all.
+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
//
// Some secondary priorities arise directly from the first two, some of which
// make more explicit reasons why performance can't be emphasized.
//
// - Portable ("ease of use")
-// - Small footprint ("easy to maintain")
+// - Small source code footprint ("easy to maintain")
// - No dependencies ("ease of use")
//
// ===========================================================================
@@ -313,13 +209,6 @@ License:
// (at least this is true for iOS and Android). Therefore, the NEON support is
// toggled by a build flag: define STBI_NEON to get NEON loops.
//
-// The output of the JPEG decoder is slightly different from versions where
-// SIMD support was introduced (that is, for versions before 1.49). The
-// difference is only +-1 in the 8-bit RGB channels, and only on a small
-// fraction of pixels. You can force the pre-1.49 behavior by defining
-// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path
-// and hence cost some performance.
-//
// If for some reason you do not want to use any of SIMD code, or if
// you have issues compiling it, you can disable it entirely by
// defining STBI_NO_SIMD.
@@ -375,6 +264,41 @@ License:
// says there's premultiplied data (currently only happens in iPhone images,
// and only if iPhone convert-to-rgb processing is on).
//
+// ===========================================================================
+//
+// ADDITIONAL CONFIGURATION
+//
+// - You can suppress implementation of any of the decoders to reduce
+// your code footprint by #defining one or more of the following
+// symbols before creating the implementation.
+//
+// STBI_NO_JPEG
+// STBI_NO_PNG
+// STBI_NO_BMP
+// STBI_NO_PSD
+// STBI_NO_TGA
+// STBI_NO_GIF
+// STBI_NO_HDR
+// STBI_NO_PIC
+// STBI_NO_PNM (.ppm and .pgm)
+//
+// - You can request *only* certain decoders and suppress all other ones
+// (this will be more forward-compatible, as addition of new decoders
+// doesn't require you to disable them explicitly):
+//
+// STBI_ONLY_JPEG
+// STBI_ONLY_PNG
+// STBI_ONLY_BMP
+// STBI_ONLY_PSD
+// STBI_ONLY_TGA
+// STBI_ONLY_GIF
+// STBI_ONLY_HDR
+// STBI_ONLY_PIC
+// STBI_ONLY_PNM (.ppm and .pgm)
+//
+// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
+// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
+//
#ifndef STBI_NO_STDIO
@@ -385,7 +309,7 @@ License:
enum
{
- STBI_default = 0, // only used for req_comp
+ STBI_default = 0, // only used for desired_channels
STBI_grey = 1,
STBI_grey_alpha = 2,
@@ -394,6 +318,7 @@ enum
};
typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
#ifdef __cplusplus
extern "C" {
@@ -421,34 +346,56 @@ typedef struct
int (*eof) (void *user); // returns nonzero if we are at end of file/data
} stbi_io_callbacks;
-STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp);
-STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp);
+////////////////////////////////////
+//
+// 8-bits-per-channel interface
+//
+
+STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
#ifndef STBI_NO_STDIO
-STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
+STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
// for stbi_load_from_file, file pointer is left pointing immediately after image
#endif
+////////////////////////////////////
+//
+// 16-bits-per-channel interface
+//
+
+STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
+
+////////////////////////////////////
+//
+// float-per-channel interface
+//
#ifndef STBI_NO_LINEAR
- STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
- STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
- STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
+ STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+ STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
#ifndef STBI_NO_STDIO
- STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
+ STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+ STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
#endif
#endif
#ifndef STBI_NO_HDR
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
STBIDEF void stbi_hdr_to_ldr_scale(float scale);
-#endif
+#endif // STBI_NO_HDR
#ifndef STBI_NO_LINEAR
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
STBIDEF void stbi_ldr_to_hdr_scale(float scale);
-#endif // STBI_NO_HDR
+#endif // STBI_NO_LINEAR
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
@@ -487,6 +434,8 @@ STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultipl
// or just pass them through "as-is"
STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
+// flip the image vertically, so the first pixel in the output array is the bottom left
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes
@@ -552,6 +501,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#include <stddef.h> // ptrdiff_t on osx
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
#include <math.h> // ldexp
@@ -610,29 +560,58 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
#define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
#endif
-#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC)
+#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
// ok
-#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC)
+#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
// ok
#else
-#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC."
+#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
#endif
#ifndef STBI_MALLOC
-#define STBI_MALLOC(sz) malloc(sz)
-#define STBI_REALLOC(p,sz) realloc(p,sz)
-#define STBI_FREE(p) free(p)
+#define STBI_MALLOC(sz) malloc(sz)
+#define STBI_REALLOC(p,newsz) realloc(p,newsz)
+#define STBI_FREE(p) free(p)
+#endif
+
+#ifndef STBI_REALLOC_SIZED
+#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
+#endif
+
+// x86/x64 detection
+#if defined(__x86_64__) || defined(_M_X64)
+#define STBI__X64_TARGET
+#elif defined(__i386) || defined(_M_IX86)
+#define STBI__X86_TARGET
#endif
-#if defined(__GNUC__) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
+#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
-// (but compiling with -msse2 allows the compiler to use SSE2 everywhere;
-// this is just broken and gcc are jerks for not fixing it properly
-// http://www.virtualdub.org/blog/pivot/entry.php?id=363 )
+// which in turn means it gets to use SSE2 everywhere. This is unfortunate,
+// but previous attempts to provide the SSE2 functions with runtime
+// detection caused numerous issues. The way architecture extensions are
+// exposed in GCC/Clang is, sadly, not really suited for one-file libs.
+// New behavior: if compiled with -msse2, we use SSE2 without any
+// detection; if not, we don't use it at all.
+#define STBI_NO_SIMD
+#endif
+
+#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
+// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
+//
+// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
+// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
+// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
+// simultaneously enabling "-mstackrealign".
+//
+// See https://github.com/nothings/stb/issues/81 for more information.
+//
+// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
+// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
#define STBI_NO_SIMD
#endif
-#if !defined(STBI_NO_SIMD) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
#define STBI_SSE2
#include <emmintrin.h>
@@ -661,7 +640,7 @@ static int stbi__cpuid3(void)
#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
-static int stbi__sse2_available()
+static int stbi__sse2_available(void)
{
int info3 = stbi__cpuid3();
return ((info3 >> 26) & 1) != 0;
@@ -669,16 +648,12 @@ static int stbi__sse2_available()
#else // assume GCC-style if not VC++
#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
-static int stbi__sse2_available()
+static int stbi__sse2_available(void)
{
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later
- // GCC 4.8+ has a nice way to do this
- return __builtin_cpu_supports("sse2");
-#else
- // portable way to do this, preferably without using GCC inline ASM?
- // just bail for now.
- return 0;
-#endif
+ // If we're even attempting to compile this on GCC/Clang, that means
+ // -msse2 is on, which means the compiler is allowed to use SSE2
+ // instructions at will, and so are we.
+ return 1;
}
#endif
#endif
@@ -717,7 +692,7 @@ typedef struct
stbi_uc buffer_start[128];
stbi_uc *img_buffer, *img_buffer_end;
- stbi_uc *img_buffer_original;
+ stbi_uc *img_buffer_original, *img_buffer_original_end;
} stbi__context;
@@ -729,7 +704,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
s->io.read = NULL;
s->read_from_callbacks = 0;
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
- s->img_buffer_end = (stbi_uc *) buffer+len;
+ s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
}
// initialize a callback-based context
@@ -741,6 +716,7 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
s->read_from_callbacks = 1;
s->img_buffer_original = s->buffer_start;
stbi__refill_buffer(s);
+ s->img_buffer_original_end = s->img_buffer_end;
}
#ifndef STBI_NO_STDIO
@@ -782,59 +758,73 @@ static void stbi__rewind(stbi__context *s)
// but we just rewind to the beginning of the initial buffer, because
// we only use it after doing 'test', which only ever looks at at most 92 bytes
s->img_buffer = s->img_buffer_original;
+ s->img_buffer_end = s->img_buffer_original_end;
}
+enum
+{
+ STBI_ORDER_RGB,
+ STBI_ORDER_BGR
+};
+
+typedef struct
+{
+ int bits_per_channel;
+ int num_channels;
+ int channel_order;
+} stbi__result_info;
+
#ifndef STBI_NO_JPEG
static int stbi__jpeg_test(stbi__context *s);
-static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PNG
static int stbi__png_test(stbi__context *s);
-static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_BMP
static int stbi__bmp_test(stbi__context *s);
-static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_TGA
static int stbi__tga_test(stbi__context *s);
-static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PSD
static int stbi__psd_test(stbi__context *s);
-static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_HDR
static int stbi__hdr_test(stbi__context *s);
-static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PIC
static int stbi__pic_test(stbi__context *s);
-static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_GIF
static int stbi__gif_test(stbi__context *s);
-static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
#endif
#ifndef STBI_NO_PNM
static int stbi__pnm_test(stbi__context *s);
-static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif
@@ -857,6 +847,77 @@ static void *stbi__malloc(size_t size)
return STBI_MALLOC(size);
}
+// stb_image uses ints pervasively, including for offset calculations.
+// therefore the largest decoded image size we can support with the
+// current code, even on 64-bit targets, is INT_MAX. this is not a
+// significant limitation for the intended use case.
+//
+// we do, however, need to make sure our size calculations don't
+// overflow. hence a few helper functions for size calculations that
+// multiply integers together, making sure that they're non-negative
+// and no overflow occurs.
+
+// return 1 if the sum is valid, 0 on overflow.
+// negative terms are considered invalid.
+static int stbi__addsizes_valid(int a, int b)
+{
+ if (b < 0) return 0;
+ // now 0 <= b <= INT_MAX, hence also
+ // 0 <= INT_MAX - b <= INTMAX.
+ // And "a + b <= INT_MAX" (which might overflow) is the
+ // same as a <= INT_MAX - b (no overflow)
+ return a <= INT_MAX - b;
+}
+
+// returns 1 if the product is valid, 0 on overflow.
+// negative factors are considered invalid.
+static int stbi__mul2sizes_valid(int a, int b)
+{
+ if (a < 0 || b < 0) return 0;
+ if (b == 0) return 1; // mul-by-0 is always safe
+ // portable way to check for no overflows in a*b
+ return a <= INT_MAX/b;
+}
+
+// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad2sizes_valid(int a, int b, int add)
+{
+ return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
+}
+
+// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad3sizes_valid(int a, int b, int c, int add)
+{
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+ stbi__addsizes_valid(a*b*c, add);
+}
+
+// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
+{
+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+ stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
+}
+
+// mallocs with size overflow checking
+static void *stbi__malloc_mad2(int a, int b, int add)
+{
+ if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
+ return stbi__malloc(a*b + add);
+}
+
+static void *stbi__malloc_mad3(int a, int b, int c, int add)
+{
+ if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
+ return stbi__malloc(a*b*c + add);
+}
+
+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
+{
+ if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
+ return stbi__malloc(a*b*c*d + add);
+}
+
// stbi__err - error
// stbi__errpf - error returning pointer to float
// stbi__errpuc - error returning pointer to unsigned char
@@ -869,8 +930,8 @@ static void *stbi__malloc(size_t size)
#define stbi__err(x,y) stbi__err(x)
#endif
-#define stbi__errpf(x,y) ((float *) (stbi__err(x,y)?NULL:NULL))
-#define stbi__errpuc(x,y) ((unsigned char *) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
STBIDEF void stbi_image_free(void *retval_from_stbi_load)
{
@@ -885,33 +946,45 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif
-static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static int stbi__vertically_flip_on_load = 0;
+
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{
+ stbi__vertically_flip_on_load = flag_true_if_should_flip;
+}
+
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+ memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
+ ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
+ ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
+ ri->num_channels = 0;
+
#ifndef STBI_NO_JPEG
- if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp);
+ if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_PNG
- if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp);
+ if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_BMP
- if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp);
+ if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_GIF
- if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp);
+ if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_PSD
- if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp);
+ if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
#endif
#ifndef STBI_NO_PIC
- if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp);
+ if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_PNM
- if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp);
+ if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri);
#endif
#ifndef STBI_NO_HDR
if (stbi__hdr_test(s)) {
- float *hdr = stbi__hdr_load(s, x,y,comp,req_comp);
+ float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
}
#endif
@@ -919,12 +992,127 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp
#ifndef STBI_NO_TGA
// test tga last because it's a crappy test!
if (stbi__tga_test(s))
- return stbi__tga_load(s,x,y,comp,req_comp);
+ return stbi__tga_load(s,x,y,comp,req_comp, ri);
#endif
return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
}
+static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
+{
+ int i;
+ int img_len = w * h * channels;
+ stbi_uc *reduced;
+
+ reduced = (stbi_uc *) stbi__malloc(img_len);
+ if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+
+ for (i = 0; i < img_len; ++i)
+ reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
+
+ STBI_FREE(orig);
+ return reduced;
+}
+
+static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
+{
+ int i;
+ int img_len = w * h * channels;
+ stbi__uint16 *enlarged;
+
+ enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
+ if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+
+ for (i = 0; i < img_len; ++i)
+ enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+
+ STBI_FREE(orig);
+ return enlarged;
+}
+
+static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
+{
+ int row;
+ size_t bytes_per_row = (size_t)w * bytes_per_pixel;
+ stbi_uc temp[2048];
+ stbi_uc *bytes = (stbi_uc *)image;
+
+ for (row = 0; row < (h>>1); row++) {
+ stbi_uc *row0 = bytes + row*bytes_per_row;
+ stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
+ // swap row0 with row1
+ size_t bytes_left = bytes_per_row;
+ while (bytes_left) {
+ size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
+ memcpy(temp, row0, bytes_copy);
+ memcpy(row0, row1, bytes_copy);
+ memcpy(row1, temp, bytes_copy);
+ row0 += bytes_copy;
+ row1 += bytes_copy;
+ bytes_left -= bytes_copy;
+ }
+ }
+}
+
+static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+ stbi__result_info ri;
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+
+ if (result == NULL)
+ return NULL;
+
+ if (ri.bits_per_channel != 8) {
+ STBI_ASSERT(ri.bits_per_channel == 16);
+ result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+ ri.bits_per_channel = 8;
+ }
+
+ // @TODO: move stbi__convert_format to here
+
+ if (stbi__vertically_flip_on_load) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+ }
+
+ return (unsigned char *) result;
+}
+
+static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+ stbi__result_info ri;
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+
+ if (result == NULL)
+ return NULL;
+
+ if (ri.bits_per_channel != 16) {
+ STBI_ASSERT(ri.bits_per_channel == 8);
+ result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+ ri.bits_per_channel = 16;
+ }
+
+ // @TODO: move stbi__convert_format16 to here
+ // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
+
+ if (stbi__vertically_flip_on_load) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
+ }
+
+ return (stbi__uint16 *) result;
+}
+
+#ifndef STBI_NO_HDR
+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
+{
+ if (stbi__vertically_flip_on_load && result != NULL) {
+ int channels = req_comp ? req_comp : *comp;
+ stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
+ }
+}
+#endif
+
#ifndef STBI_NO_STDIO
static FILE *stbi__fopen(char const *filename, char const *mode)
@@ -955,38 +1143,82 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req
unsigned char *result;
stbi__context s;
stbi__start_file(&s,f);
- result = stbi_load_main(&s,x,y,comp,req_comp);
+ result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+ if (result) {
+ // need to 'unget' all the characters in the IO buffer
+ fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+ }
+ return result;
+}
+
+STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+ stbi__uint16 *result;
+ stbi__context s;
+ stbi__start_file(&s,f);
+ result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
if (result) {
// need to 'unget' all the characters in the IO buffer
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
}
return result;
}
+
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+ FILE *f = stbi__fopen(filename, "rb");
+ stbi__uint16 *result;
+ if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
+ result = stbi_load_from_file_16(f,x,y,comp,req_comp);
+ fclose(f);
+ return result;
+}
+
+
#endif //!STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+ stbi__context s;
+ stbi__start_mem(&s,buffer,len);
+ return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+ stbi__context s;
+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+ return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_mem(&s,buffer,len);
- return stbi_load_main(&s,x,y,comp,req_comp);
+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
}
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
- return stbi_load_main(&s,x,y,comp,req_comp);
+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
}
#ifndef STBI_NO_LINEAR
-static float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
unsigned char *data;
#ifndef STBI_NO_HDR
- if (stbi__hdr_test(s))
- return stbi__hdr_load(s,x,y,comp,req_comp);
+ if (stbi__hdr_test(s)) {
+ stbi__result_info ri;
+ float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
+ if (hdr_data)
+ stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
+ return hdr_data;
+ }
#endif
- data = stbi_load_main(s, x, y, comp, req_comp);
+ data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
if (data)
return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
@@ -996,14 +1228,14 @@ STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, in
{
stbi__context s;
stbi__start_mem(&s,buffer,len);
- return stbi_loadf_main(&s,x,y,comp,req_comp);
+ return stbi__loadf_main(&s,x,y,comp,req_comp);
}
STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
- return stbi_loadf_main(&s,x,y,comp,req_comp);
+ return stbi__loadf_main(&s,x,y,comp,req_comp);
}
#ifndef STBI_NO_STDIO
@@ -1021,7 +1253,7 @@ STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_
{
stbi__context s;
stbi__start_file(&s,f);
- return stbi_loadf_main(&s,x,y,comp,req_comp);
+ return stbi__loadf_main(&s,x,y,comp,req_comp);
}
#endif // !STBI_NO_STDIO
@@ -1063,6 +1295,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f)
stbi__start_file(&s,f);
return stbi__hdr_test(&s);
#else
+ STBI_NOTUSED(f);
return 0;
#endif
}
@@ -1075,18 +1308,21 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi__hdr_test(&s);
#else
+ STBI_NOTUSED(clbk);
+ STBI_NOTUSED(user);
return 0;
#endif
}
-static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
+#ifndef STBI_NO_LINEAR
static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
-#ifndef STBI_NO_LINEAR
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
#endif
+static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
+
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
@@ -1144,6 +1380,10 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
static void stbi__skip(stbi__context *s, int n)
{
+ if (n < 0) {
+ s->img_buffer = s->img_buffer_end;
+ return;
+ }
if (s->io.read) {
int blen = (int) (s->img_buffer_end - s->img_buffer);
if (blen < n) {
@@ -1191,17 +1431,23 @@ static stbi__uint32 stbi__get32be(stbi__context *s)
return (z << 16) + stbi__get16be(s);
}
+#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
+// nothing
+#else
static int stbi__get16le(stbi__context *s)
{
int z = stbi__get8(s);
return z + (stbi__get8(s) << 8);
}
+#endif
+#ifndef STBI_NO_BMP
static stbi__uint32 stbi__get32le(stbi__context *s)
{
stbi__uint32 z = stbi__get16le(s);
return z + (stbi__get16le(s) << 16);
}
+#endif
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
@@ -1230,7 +1476,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
if (req_comp == img_n) return data;
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
- good = (unsigned char *) stbi__malloc(req_comp * x * y);
+ good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
if (good == NULL) {
STBI_FREE(data);
return stbi__errpuc("outofmem", "Out of memory");
@@ -1240,26 +1486,75 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
unsigned char *src = data + j * x * img_n ;
unsigned char *dest = good + j * x * req_comp;
- #define COMBO(a,b) ((a)*8+(b))
- #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+ #define STBI__COMBO(a,b) ((a)*8+(b))
+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
// convert source image with img_n components to one with req_comp components;
// avoid switch per pixel, so use switch per scanline and massive macros
- switch (COMBO(img_n, req_comp)) {
- CASE(1,2) dest[0]=src[0], dest[1]=255; break;
- CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break;
- CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break;
- CASE(2,1) dest[0]=src[0]; break;
- CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break;
- CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break;
- CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break;
- CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break;
- CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break;
- CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break;
- CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break;
- CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break;
+ switch (STBI__COMBO(img_n, req_comp)) {
+ STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break;
+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break;
+ STBI__CASE(2,1) { dest[0]=src[0]; } break;
+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
+ STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break;
+ STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
+ STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break;
+ STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
+ STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+ STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
default: STBI_ASSERT(0);
}
- #undef CASE
+ #undef STBI__CASE
+ }
+
+ STBI_FREE(data);
+ return good;
+}
+
+static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
+{
+ return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
+}
+
+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+ int i,j;
+ stbi__uint16 *good;
+
+ if (req_comp == img_n) return data;
+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+ good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
+ if (good == NULL) {
+ STBI_FREE(data);
+ return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+ }
+
+ for (j=0; j < (int) y; ++j) {
+ stbi__uint16 *src = data + j * x * img_n ;
+ stbi__uint16 *dest = good + j * x * req_comp;
+
+ #define STBI__COMBO(a,b) ((a)*8+(b))
+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+ // convert source image with img_n components to one with req_comp components;
+ // avoid switch per pixel, so use switch per scanline and massive macros
+ switch (STBI__COMBO(img_n, req_comp)) {
+ STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break;
+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break;
+ STBI__CASE(2,1) { dest[0]=src[0]; } break;
+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
+ STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break;
+ STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
+ STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break;
+ STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
+ STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break;
+ STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
+ default: STBI_ASSERT(0);
+ }
+ #undef STBI__CASE
}
STBI_FREE(data);
@@ -1270,7 +1565,9 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
{
int i,k,n;
- float *output = (float *) stbi__malloc(x * y * comp * sizeof(float));
+ float *output;
+ if (!data) return NULL;
+ output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
// compute number of non-alpha components
if (comp & 1) n = comp; else n = comp-1;
@@ -1290,7 +1587,9 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)
{
int i,k,n;
- stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp);
+ stbi_uc *output;
+ if (!data) return NULL;
+ output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
// compute number of non-alpha components
if (comp & 1) n = comp; else n = comp-1;
@@ -1355,7 +1654,7 @@ typedef struct
stbi__context *s;
stbi__huffman huff_dc[4];
stbi__huffman huff_ac[4];
- stbi_uc dequant[4][64];
+ stbi__uint16 dequant[4][64];
stbi__int16 fast_ac[4][1 << FAST_BITS];
// sizes for components, interleaved MCUs
@@ -1391,6 +1690,9 @@ typedef struct
int succ_high;
int succ_low;
int eob_run;
+ int jfif;
+ int app14_color_transform; // Adobe APP14 tag
+ int rgb;
int scan_n, order[4];
int restart_interval, todo;
@@ -1460,7 +1762,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
// magnitude code followed by receive_extend code
int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
int m = 1 << (magbits - 1);
- if (k < m) k += (-1 << magbits) + 1;
+ if (k < m) k += (~0U << magbits) + 1;
// if the result is small enough, we can fit it in fast_ac table
if (k >= -128 && k <= 127)
fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits));
@@ -1475,6 +1777,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
int b = j->nomore ? 0 : stbi__get8(j->s);
if (b == 0xff) {
int c = stbi__get8(j->s);
+ while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
if (c != 0) {
j->marker = (unsigned char) c;
j->nomore = 1;
@@ -1552,6 +1855,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
k = stbi_lrot(j->code_buffer, n);
+ STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n];
j->code_bits -= n;
@@ -1598,7 +1902,7 @@ static stbi_uc stbi__jpeg_dezigzag[64+15] =
};
// decode one 64-entry block--
-static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant)
+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
{
int diff,dc,k;
int t;
@@ -1757,8 +2061,11 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
if (r)
j->eob_run += stbi__jpeg_get_bits(j, r);
r = 64; // force end of block
- } else
- r = 16; // r=15 is the code for 16 0s
+ } else {
+ // r=15 s=0 should write 16 0s, so we just do
+ // a run of 15 0s and then write s (which is 0),
+ // so we don't have to do anything special here
+ }
} else {
if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
// sign bit
@@ -1770,7 +2077,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
// advance by r
while (k <= j->spec_end) {
- short *p = &data[stbi__jpeg_dezigzag[k]];
+ short *p = &data[stbi__jpeg_dezigzag[k++]];
if (*p != 0) {
if (stbi__jpeg_get_bit(j))
if ((*p & bit)==0) {
@@ -1779,15 +2086,12 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
else
*p -= bit;
}
- ++k;
} else {
if (r == 0) {
- if (s)
- data[stbi__jpeg_dezigzag[k++]] = (short) s;
+ *p = (short) s;
break;
}
--r;
- ++k;
}
}
} while (k <= j->spec_end);
@@ -2307,7 +2611,7 @@ static stbi_uc stbi__get_marker(stbi__jpeg *j)
x = stbi__get8(j->s);
if (x != 0xff) return STBI__MARKER_none;
while (x == 0xff)
- x = stbi__get8(j->s);
+ x = stbi__get8(j->s); // consume repeated 0xff fill bytes
return x;
}
@@ -2322,7 +2626,7 @@ static void stbi__jpeg_reset(stbi__jpeg *j)
j->code_bits = 0;
j->code_buffer = 0;
j->nomore = 0;
- j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0;
+ j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
j->marker = STBI__MARKER_none;
j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
j->eob_run = 0;
@@ -2454,7 +2758,7 @@ static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
}
}
-static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant)
+static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
{
int i;
for (i=0; i < 64; ++i)
@@ -2496,13 +2800,14 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
L = stbi__get16be(z->s)-2;
while (L > 0) {
int q = stbi__get8(z->s);
- int p = q >> 4;
+ int p = q >> 4, sixteen = (p != 0);
int t = q & 15,i;
- if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG");
+ if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
+
for (i=0; i < 64; ++i)
- z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s);
- L -= 65;
+ z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
+ L -= (sixteen ? 129 : 65);
}
return L==0;
@@ -2535,12 +2840,50 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
}
return L==0;
}
+
// check for comment block or APP blocks
if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
- stbi__skip(z->s, stbi__get16be(z->s)-2);
+ L = stbi__get16be(z->s);
+ if (L < 2) {
+ if (m == 0xFE)
+ return stbi__err("bad COM len","Corrupt JPEG");
+ else
+ return stbi__err("bad APP len","Corrupt JPEG");
+ }
+ L -= 2;
+
+ if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
+ static const unsigned char tag[5] = {'J','F','I','F','\0'};
+ int ok = 1;
+ int i;
+ for (i=0; i < 5; ++i)
+ if (stbi__get8(z->s) != tag[i])
+ ok = 0;
+ L -= 5;
+ if (ok)
+ z->jfif = 1;
+ } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
+ static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
+ int ok = 1;
+ int i;
+ for (i=0; i < 6; ++i)
+ if (stbi__get8(z->s) != tag[i])
+ ok = 0;
+ L -= 6;
+ if (ok) {
+ stbi__get8(z->s); // version
+ stbi__get16be(z->s); // flags0
+ stbi__get16be(z->s); // flags1
+ z->app14_color_transform = stbi__get8(z->s); // color transform
+ L -= 6;
+ }
+ }
+
+ stbi__skip(z->s, L);
return 1;
}
- return 0;
+
+ return stbi__err("unknown marker","Corrupt JPEG");
}
// after we see SOS
@@ -2583,6 +2926,28 @@ static int stbi__process_scan_header(stbi__jpeg *z)
return 1;
}
+static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
+{
+ int i;
+ for (i=0; i < ncomp; ++i) {
+ if (z->img_comp[i].raw_data) {
+ STBI_FREE(z->img_comp[i].raw_data);
+ z->img_comp[i].raw_data = NULL;
+ z->img_comp[i].data = NULL;
+ }
+ if (z->img_comp[i].raw_coeff) {
+ STBI_FREE(z->img_comp[i].raw_coeff);
+ z->img_comp[i].raw_coeff = 0;
+ z->img_comp[i].coeff = 0;
+ }
+ if (z->img_comp[i].linebuf) {
+ STBI_FREE(z->img_comp[i].linebuf);
+ z->img_comp[i].linebuf = NULL;
+ }
+ }
+ return why;
+}
+
static int stbi__process_frame_header(stbi__jpeg *z, int scan)
{
stbi__context *s = z->s;
@@ -2592,7 +2957,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
c = stbi__get8(s);
- if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires
+ if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
s->img_n = c;
for (i=0; i < c; ++i) {
z->img_comp[i].data = NULL;
@@ -2601,11 +2966,12 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
+ z->rgb = 0;
for (i=0; i < s->img_n; ++i) {
+ static unsigned char rgb[3] = { 'R', 'G', 'B' };
z->img_comp[i].id = stbi__get8(s);
- if (z->img_comp[i].id != i+1) // JFIF requires
- if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files!
- return stbi__err("bad component ID","Corrupt JPEG");
+ if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
+ ++z->rgb;
q = stbi__get8(s);
z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
@@ -2614,7 +2980,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
if (scan != STBI__SCAN_load) return 1;
- if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
+ if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
for (i=0; i < s->img_n; ++i) {
if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
@@ -2626,6 +2992,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
z->img_v_max = v_max;
z->img_mcu_w = h_max * 8;
z->img_mcu_h = v_max * 8;
+ // these sizes can't be more than 17 bits
z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
@@ -2637,28 +3004,27 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
// the bogus oversized data from using interleaved MCUs and their
// big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
// discard the extra data until colorspace conversion
+ //
+ // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
+ // so these muls can't overflow with 32-bit ints (which we require)
z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
- z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
-
- if (z->img_comp[i].raw_data == NULL) {
- for(--i; i >= 0; --i) {
- STBI_FREE(z->img_comp[i].raw_data);
- z->img_comp[i].data = NULL;
- }
- return stbi__err("outofmem", "Out of memory");
- }
+ z->img_comp[i].coeff = 0;
+ z->img_comp[i].raw_coeff = 0;
+ z->img_comp[i].linebuf = NULL;
+ z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
+ if (z->img_comp[i].raw_data == NULL)
+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
// align blocks for idct using mmx/sse
z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
- z->img_comp[i].linebuf = NULL;
if (z->progressive) {
- z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3;
- z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3;
- z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15);
+ // w2, h2 are multiples of 8 (see above)
+ z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
+ z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
+ z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
+ if (z->img_comp[i].raw_coeff == NULL)
+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
- } else {
- z->img_comp[i].coeff = 0;
- z->img_comp[i].raw_coeff = 0;
}
}
@@ -2677,6 +3043,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
{
int m;
+ z->jfif = 0;
+ z->app14_color_transform = -1; // valid values are 0,1,2
z->marker = STBI__MARKER_none; // initialize cached marker to empty
m = stbi__get_marker(z);
if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
@@ -2700,6 +3068,10 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
static int stbi__decode_jpeg_image(stbi__jpeg *j)
{
int m;
+ for (m = 0; m < 4; m++) {
+ j->img_comp[m].raw_data = NULL;
+ j->img_comp[m].raw_coeff = NULL;
+ }
j->restart_interval = 0;
if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
m = stbi__get_marker(j);
@@ -2714,12 +3086,15 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j)
if (x == 255) {
j->marker = stbi__get8(j->s);
break;
- } else if (x != 0) {
- return stbi__err("junk before marker", "Corrupt JPEG");
}
}
// if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
}
+ } else if (stbi__DNL(m)) {
+ int Ld = stbi__get16be(j->s);
+ stbi__uint32 NL = stbi__get16be(j->s);
+ if (Ld != 4) stbi__err("bad DNL len", "Corrupt JPEG");
+ if (NL != j->s->img_y) stbi__err("bad DNL height", "Corrupt JPEG");
} else {
if (!stbi__process_marker(j, m)) return 0;
}
@@ -2938,38 +3313,9 @@ static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_
return out;
}
-#ifdef STBI_JPEG_OLD
-// this is the same YCbCr-to-RGB calculation that stb_image has used
-// historically before the algorithm changes in 1.49
-#define float2fixed(x) ((int) ((x) * 65536 + 0.5))
-static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
-{
- int i;
- for (i=0; i < count; ++i) {
- int y_fixed = (y[i] << 16) + 32768; // rounding
- int r,g,b;
- int cr = pcr[i] - 128;
- int cb = pcb[i] - 128;
- r = y_fixed + cr*float2fixed(1.40200f);
- g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f);
- b = y_fixed + cb*float2fixed(1.77200f);
- r >>= 16;
- g >>= 16;
- b >>= 16;
- if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
- if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
- if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
- out[0] = (stbi_uc)r;
- out[1] = (stbi_uc)g;
- out[2] = (stbi_uc)b;
- out[3] = 255;
- out += step;
- }
-}
-#else
// this is a reduced-precision calculation of YCbCr-to-RGB introduced
// to make sure the code produces the same results in both SIMD and scalar
-#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8)
+#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8)
static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
{
int i;
@@ -2978,9 +3324,9 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc
int r,g,b;
int cr = pcr[i] - 128;
int cb = pcb[i] - 128;
- r = y_fixed + cr* float2fixed(1.40200f);
- g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000);
- b = y_fixed + cb* float2fixed(1.77200f);
+ r = y_fixed + cr* stbi__float2fixed(1.40200f);
+ g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+ b = y_fixed + cb* stbi__float2fixed(1.77200f);
r >>= 20;
g >>= 20;
b >>= 20;
@@ -2994,7 +3340,6 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc
out += step;
}
}
-#endif
#if defined(STBI_SSE2) || defined(STBI_NEON)
static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
@@ -3113,9 +3458,9 @@ static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc cons
int r,g,b;
int cr = pcr[i] - 128;
int cb = pcb[i] - 128;
- r = y_fixed + cr* float2fixed(1.40200f);
- g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000);
- b = y_fixed + cb* float2fixed(1.77200f);
+ r = y_fixed + cr* stbi__float2fixed(1.40200f);
+ g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+ b = y_fixed + cb* stbi__float2fixed(1.77200f);
r >>= 20;
g >>= 20;
b >>= 20;
@@ -3141,18 +3486,14 @@ static void stbi__setup_jpeg(stbi__jpeg *j)
#ifdef STBI_SSE2
if (stbi__sse2_available()) {
j->idct_block_kernel = stbi__idct_simd;
- #ifndef STBI_JPEG_OLD
j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
- #endif
j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
}
#endif
#ifdef STBI_NEON
j->idct_block_kernel = stbi__idct_simd;
- #ifndef STBI_JPEG_OLD
j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
- #endif
j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
#endif
}
@@ -3160,23 +3501,7 @@ static void stbi__setup_jpeg(stbi__jpeg *j)
// clean up the temporary component buffers
static void stbi__cleanup_jpeg(stbi__jpeg *j)
{
- int i;
- for (i=0; i < j->s->img_n; ++i) {
- if (j->img_comp[i].raw_data) {
- STBI_FREE(j->img_comp[i].raw_data);
- j->img_comp[i].raw_data = NULL;
- j->img_comp[i].data = NULL;
- }
- if (j->img_comp[i].raw_coeff) {
- STBI_FREE(j->img_comp[i].raw_coeff);
- j->img_comp[i].raw_coeff = 0;
- j->img_comp[i].coeff = 0;
- }
- if (j->img_comp[i].linebuf) {
- STBI_FREE(j->img_comp[i].linebuf);
- j->img_comp[i].linebuf = NULL;
- }
- }
+ stbi__free_jpeg_components(j, j->s->img_n, 0);
}
typedef struct
@@ -3189,9 +3514,16 @@ typedef struct
int ypos; // which pre-expansion row we're on
} stbi__resample;
+// fast 0..255 * 0..255 => 0..255 rounded multiplication
+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
+{
+ unsigned int t = x*y + 128;
+ return (stbi_uc) ((t + (t >>8)) >> 8);
+}
+
static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
{
- int n, decode_n;
+ int n, decode_n, is_rgb;
z->s->img_n = 0; // make stbi__cleanup_jpeg safe
// validate req_comp
@@ -3201,9 +3533,11 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
// determine actual number of components to generate
- n = req_comp ? req_comp : z->s->img_n;
+ n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
- if (z->s->img_n == 3 && n < 3)
+ is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
+
+ if (z->s->img_n == 3 && n < 3 && !is_rgb)
decode_n = 1;
else
decode_n = z->s->img_n;
@@ -3240,7 +3574,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
}
// can't error after this so, this is safe
- output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1);
+ output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
// now go ahead and resample
@@ -3263,7 +3597,39 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
if (n >= 3) {
stbi_uc *y = coutput[0];
if (z->s->img_n == 3) {
- z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ if (is_rgb) {
+ for (i=0; i < z->s->img_x; ++i) {
+ out[0] = y[i];
+ out[1] = coutput[1][i];
+ out[2] = coutput[2][i];
+ out[3] = 255;
+ out += n;
+ }
+ } else {
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ }
+ } else if (z->s->img_n == 4) {
+ if (z->app14_color_transform == 0) { // CMYK
+ for (i=0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ out[0] = stbi__blinn_8x8(coutput[0][i], m);
+ out[1] = stbi__blinn_8x8(coutput[1][i], m);
+ out[2] = stbi__blinn_8x8(coutput[2][i], m);
+ out[3] = 255;
+ out += n;
+ }
+ } else if (z->app14_color_transform == 2) { // YCCK
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ for (i=0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ out[0] = stbi__blinn_8x8(255 - out[0], m);
+ out[1] = stbi__blinn_8x8(255 - out[1], m);
+ out[2] = stbi__blinn_8x8(255 - out[2], m);
+ out += n;
+ }
+ } else { // YCbCr + alpha? Ignore the fourth channel for now
+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+ }
} else
for (i=0; i < z->s->img_x; ++i) {
out[0] = out[1] = out[2] = y[i];
@@ -3271,37 +3637,70 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
out += n;
}
} else {
- stbi_uc *y = coutput[0];
- if (n == 1)
- for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
- else
- for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255;
+ if (is_rgb) {
+ if (n == 1)
+ for (i=0; i < z->s->img_x; ++i)
+ *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+ else {
+ for (i=0; i < z->s->img_x; ++i, out += 2) {
+ out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+ out[1] = 255;
+ }
+ }
+ } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
+ for (i=0; i < z->s->img_x; ++i) {
+ stbi_uc m = coutput[3][i];
+ stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
+ stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
+ stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
+ out[0] = stbi__compute_y(r, g, b);
+ out[1] = 255;
+ out += n;
+ }
+ } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
+ for (i=0; i < z->s->img_x; ++i) {
+ out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
+ out[1] = 255;
+ out += n;
+ }
+ } else {
+ stbi_uc *y = coutput[0];
+ if (n == 1)
+ for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
+ else
+ for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255;
+ }
}
}
stbi__cleanup_jpeg(z);
*out_x = z->s->img_x;
*out_y = z->s->img_y;
- if (comp) *comp = z->s->img_n; // report original components, not output
+ if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
return output;
}
}
-static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
- stbi__jpeg j;
- j.s = s;
- stbi__setup_jpeg(&j);
- return load_jpeg_image(&j, x,y,comp,req_comp);
+ unsigned char* result;
+ stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+ STBI_NOTUSED(ri);
+ j->s = s;
+ stbi__setup_jpeg(j);
+ result = load_jpeg_image(j, x,y,comp,req_comp);
+ STBI_FREE(j);
+ return result;
}
static int stbi__jpeg_test(stbi__context *s)
{
int r;
- stbi__jpeg j;
- j.s = s;
- stbi__setup_jpeg(&j);
- r = stbi__decode_jpeg_header(&j, STBI__SCAN_type);
+ stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
+ j->s = s;
+ stbi__setup_jpeg(j);
+ r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
stbi__rewind(s);
+ STBI_FREE(j);
return r;
}
@@ -3313,15 +3712,18 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
}
if (x) *x = j->s->img_x;
if (y) *y = j->s->img_y;
- if (comp) *comp = j->s->img_n;
+ if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
return 1;
}
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
{
- stbi__jpeg j;
- j.s = s;
- return stbi__jpeg_info_raw(&j, x, y, comp);
+ int result;
+ stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+ j->s = s;
+ result = stbi__jpeg_info_raw(j, x, y, comp);
+ STBI_FREE(j);
+ return result;
}
#endif
@@ -3367,7 +3769,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits)
return stbi__bitreverse16(v) >> (16-bits);
}
-static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
+static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
{
int i,k=0;
int code, next_code[16], sizes[17];
@@ -3379,7 +3781,8 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
++sizes[sizelist[i]];
sizes[0] = 0;
for (i=1; i < 16; ++i)
- STBI_ASSERT(sizes[i] <= (1 << i));
+ if (sizes[i] > (1 << i))
+ return stbi__err("bad sizes", "Corrupt PNG");
code = 0;
for (i=1; i < 16; ++i) {
next_code[i] = code;
@@ -3387,7 +3790,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
z->firstsymbol[i] = (stbi__uint16) k;
code = (code + sizes[i]);
if (sizes[i])
- if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt JPEG");
+ if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
z->maxcode[i] = code << (16-i); // preshift for inner loop
code <<= 1;
k += sizes[i];
@@ -3401,10 +3804,10 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
z->size [c] = (stbi_uc ) s;
z->value[c] = (stbi__uint16) i;
if (s <= STBI__ZFAST_BITS) {
- int k = stbi__bit_reverse(next_code[s],s);
- while (k < (1 << STBI__ZFAST_BITS)) {
- z->fast[k] = fastv;
- k += (1 << s);
+ int j = stbi__bit_reverse(next_code[s],s);
+ while (j < (1 << STBI__ZFAST_BITS)) {
+ z->fast[j] = fastv;
+ j += (1 << s);
}
}
++next_code[s];
@@ -3443,7 +3846,7 @@ static void stbi__fill_bits(stbi__zbuf *z)
{
do {
STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
- z->code_buffer |= stbi__zget8(z) << z->num_bits;
+ z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
z->num_bits += 8;
} while (z->num_bits <= 24);
}
@@ -3493,14 +3896,15 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
{
char *q;
- int cur, limit;
+ int cur, limit, old_limit;
z->zout = zout;
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
cur = (int) (z->zout - z->zout_start);
- limit = (int) (z->zout_end - z->zout_start);
+ limit = old_limit = (int) (z->zout_end - z->zout_start);
while (cur + n > limit)
limit *= 2;
- q = (char *) STBI_REALLOC(z->zout_start, limit);
+ q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
+ STBI_NOTUSED(old_limit);
if (q == NULL) return stbi__err("outofmem", "Out of memory");
z->zout_start = q;
z->zout = q + cur;
@@ -3556,9 +3960,9 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
p = (stbi_uc *) (zout - dist);
if (dist == 1) { // run of one byte; common in images.
stbi_uc v = *p;
- do *zout++ = v; while (--len);
+ if (len) { do *zout++ = v; while (--len); }
} else {
- do *zout++ = *p++; while (--len);
+ if (len) { do *zout++ = *p++; while (--len); }
}
}
}
@@ -3575,6 +3979,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
int hlit = stbi__zreceive(a,5) + 257;
int hdist = stbi__zreceive(a,5) + 1;
int hclen = stbi__zreceive(a,4) + 4;
+ int ntot = hlit + hdist;
memset(codelength_sizes, 0, sizeof(codelength_sizes));
for (i=0; i < hclen; ++i) {
@@ -3584,33 +3989,35 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
n = 0;
- while (n < hlit + hdist) {
+ while (n < ntot) {
int c = stbi__zhuffman_decode(a, &z_codelength);
- STBI_ASSERT(c >= 0 && c < 19);
+ if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
if (c < 16)
lencodes[n++] = (stbi_uc) c;
- else if (c == 16) {
- c = stbi__zreceive(a,2)+3;
- memset(lencodes+n, lencodes[n-1], c);
- n += c;
- } else if (c == 17) {
- c = stbi__zreceive(a,3)+3;
- memset(lencodes+n, 0, c);
- n += c;
- } else {
- STBI_ASSERT(c == 18);
- c = stbi__zreceive(a,7)+11;
- memset(lencodes+n, 0, c);
+ else {
+ stbi_uc fill = 0;
+ if (c == 16) {
+ c = stbi__zreceive(a,2)+3;
+ if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
+ fill = lencodes[n-1];
+ } else if (c == 17)
+ c = stbi__zreceive(a,3)+3;
+ else {
+ STBI_ASSERT(c == 18);
+ c = stbi__zreceive(a,7)+11;
+ }
+ if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
+ memset(lencodes+n, fill, c);
n += c;
}
}
- if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG");
+ if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
return 1;
}
-static int stbi__parse_uncomperssed_block(stbi__zbuf *a)
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
{
stbi_uc header[4];
int len,nlen,k;
@@ -3652,9 +4059,24 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
return 1;
}
-// @TODO: should statically initialize these for optimal thread safety
-static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32];
-static void stbi__init_zdefaults(void)
+static const stbi_uc stbi__zdefault_length[288] =
+{
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
+};
+static const stbi_uc stbi__zdefault_distance[32] =
+{
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+/*
+Init algorithm:
{
int i; // use <= to match clearly with spec
for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8;
@@ -3664,6 +4086,7 @@ static void stbi__init_zdefaults(void)
for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5;
}
+*/
static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
{
@@ -3676,13 +4099,12 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2);
if (type == 0) {
- if (!stbi__parse_uncomperssed_block(a)) return 0;
+ if (!stbi__parse_uncompressed_block(a)) return 0;
} else if (type == 3) {
return 0;
} else {
if (type == 1) {
// use fixed code lengths
- if (!stbi__zdefault_distance[31]) stbi__init_zdefaults();
if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0;
if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0;
} else {
@@ -3818,6 +4240,7 @@ typedef struct
{
stbi__context *s;
stbi_uc *idata, *expanded, *out;
+ int depth;
} stbi__png;
@@ -3857,30 +4280,33 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0
// create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
{
+ int bytes = (depth == 16? 2 : 1);
stbi__context *s = a->s;
- stbi__uint32 i,j,stride = x*out_n;
+ stbi__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes;
int k;
int img_n = s->img_n; // copy it into a local for later
+ int output_bytes = out_n*bytes;
+ int filter_bytes = img_n*bytes;
+ int width = x;
+
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
- a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into
+ a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory");
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
img_len = (img_width_bytes + 1) * y;
- if (s->img_x == x && s->img_y == y) {
- if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG");
- } else { // interlaced:
- if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
- }
+ // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
+ // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
+ // so just check for raw_len < img_len always.
+ if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
for (j=0; j < y; ++j) {
stbi_uc *cur = a->out + stride*j;
- stbi_uc *prior = cur - stride;
+ stbi_uc *prior;
int filter = *raw++;
- int filter_bytes = img_n;
- int width = x;
+
if (filter > 4)
return stbi__err("invalid filter","Corrupt PNG");
@@ -3890,6 +4316,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
filter_bytes = 1;
width = img_width_bytes;
}
+ prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
// if first row, use special filter that doesn't sample previous row
if (j == 0) filter = first_row_filter[filter];
@@ -3913,6 +4340,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
raw += img_n;
cur += out_n;
prior += out_n;
+ } else if (depth == 16) {
+ if (img_n != out_n) {
+ cur[filter_bytes] = 255; // first pixel top byte
+ cur[filter_bytes+1] = 255; // first pixel bottom byte
+ }
+ raw += filter_bytes;
+ cur += output_bytes;
+ prior += output_bytes;
} else {
raw += 1;
cur += 1;
@@ -3921,38 +4356,47 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
// this is a little gross, so that we don't switch per-pixel or per-component
if (depth < 8 || img_n == out_n) {
- int nk = (width - 1)*img_n;
- #define CASE(f) \
+ int nk = (width - 1)*filter_bytes;
+ #define STBI__CASE(f) \
case f: \
for (k=0; k < nk; ++k)
switch (filter) {
// "none" filter turns into a memcpy here; make that explicit.
case STBI__F_none: memcpy(cur, raw, nk); break;
- CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break;
- CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
- CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break;
- CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break;
- CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break;
- CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break;
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
+ STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
+ STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
}
- #undef CASE
+ #undef STBI__CASE
raw += nk;
} else {
STBI_ASSERT(img_n+1 == out_n);
- #define CASE(f) \
+ #define STBI__CASE(f) \
case f: \
- for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
- for (k=0; k < img_n; ++k)
+ for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
+ for (k=0; k < filter_bytes; ++k)
switch (filter) {
- CASE(STBI__F_none) cur[k] = raw[k]; break;
- CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break;
- CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
- CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break;
- CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
- CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break;
- CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break;
+ STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
+ STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
+ STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
+ }
+ #undef STBI__CASE
+
+ // the loop above sets the high byte of the pixels' alpha, but for
+ // 16 bit png files we also need the low byte set. we'll do that here.
+ if (depth == 16) {
+ cur = a->out + stride*j; // start at the beginning of the row again
+ for (i=0; i < x; ++i,cur+=output_bytes) {
+ cur[filter_bytes+1] = 255;
+ }
}
- #undef CASE
}
}
@@ -4009,25 +4453,36 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
}
if (img_n != out_n) {
+ int q;
// insert alpha = 255
- stbi_uc *cur = a->out + stride*j;
- int i;
+ cur = a->out + stride*j;
if (img_n == 1) {
- for (i=x-1; i >= 0; --i) {
- cur[i*2+1] = 255;
- cur[i*2+0] = cur[i];
+ for (q=x-1; q >= 0; --q) {
+ cur[q*2+1] = 255;
+ cur[q*2+0] = cur[q];
}
} else {
STBI_ASSERT(img_n == 3);
- for (i=x-1; i >= 0; --i) {
- cur[i*4+3] = 255;
- cur[i*4+2] = cur[i*3+2];
- cur[i*4+1] = cur[i*3+1];
- cur[i*4+0] = cur[i*3+0];
+ for (q=x-1; q >= 0; --q) {
+ cur[q*4+3] = 255;
+ cur[q*4+2] = cur[q*3+2];
+ cur[q*4+1] = cur[q*3+1];
+ cur[q*4+0] = cur[q*3+0];
}
}
}
}
+ } else if (depth == 16) {
+ // force the image data from big-endian to platform-native.
+ // this is done in a separate pass due to the decoding relying
+ // on the data being untouched, but could probably be done
+ // per-line during decode if care is taken.
+ stbi_uc *cur = a->out;
+ stbi__uint16 *cur16 = (stbi__uint16*)cur;
+
+ for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
+ *cur16 = (cur[0] << 8) | cur[1];
+ }
}
return 1;
@@ -4035,13 +4490,15 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
{
+ int bytes = (depth == 16 ? 2 : 1);
+ int out_bytes = out_n * bytes;
stbi_uc *final;
int p;
if (!interlaced)
return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
// de-interlacing
- final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n);
+ final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
for (p=0; p < 7; ++p) {
int xorig[] = { 0,4,0,2,0,1,0 };
int yorig[] = { 0,0,4,0,2,0,1 };
@@ -4061,8 +4518,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3
for (i=0; i < x; ++i) {
int out_y = j*yspc[p]+yorig[p];
int out_x = i*xspc[p]+xorig[p];
- memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n,
- a->out + (j*x+i)*out_n, out_n);
+ memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
+ a->out + (j*x+i)*out_bytes, out_bytes);
}
}
STBI_FREE(a->out);
@@ -4100,12 +4557,37 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
return 1;
}
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
+{
+ stbi__context *s = z->s;
+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+ stbi__uint16 *p = (stbi__uint16*) z->out;
+
+ // compute color-based transparency, assuming we've
+ // already got 65535 as the alpha value in the output
+ STBI_ASSERT(out_n == 2 || out_n == 4);
+
+ if (out_n == 2) {
+ for (i = 0; i < pixel_count; ++i) {
+ p[1] = (p[0] == tc[0] ? 0 : 65535);
+ p += 2;
+ }
+ } else {
+ for (i = 0; i < pixel_count; ++i) {
+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+ p[3] = 0;
+ p += 4;
+ }
+ }
+ return 1;
+}
+
static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
{
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
stbi_uc *p, *temp_out, *orig = a->out;
- p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n);
+ p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
if (p == NULL) return stbi__err("outofmem", "Out of memory");
// between here and free(out) below, exitting would leak
@@ -4171,9 +4653,10 @@ static void stbi__de_iphone(stbi__png *z)
stbi_uc a = p[3];
stbi_uc t = p[0];
if (a) {
- p[0] = p[2] * 255 / a;
- p[1] = p[1] * 255 / a;
- p[2] = t * 255 / a;
+ stbi_uc half = a / 2;
+ p[0] = (p[2] * 255 + half) / a;
+ p[1] = (p[1] * 255 + half) / a;
+ p[2] = ( t * 255 + half) / a;
} else {
p[0] = p[2];
p[2] = t;
@@ -4198,8 +4681,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
{
stbi_uc palette[1024], pal_img_n=0;
stbi_uc has_trans=0, tc[3];
+ stbi__uint16 tc16[3];
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
- int first=1,k,interlace=0, color=0, depth=0, is_iphone=0;
+ int first=1,k,interlace=0, color=0, is_iphone=0;
stbi__context *s = z->s;
z->expanded = NULL;
@@ -4224,8 +4708,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
- depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only");
+ z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
+ if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");
@@ -4273,8 +4758,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
has_trans = 1;
- for (k=0; k < s->img_n; ++k)
- tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger
+ if (z->depth == 16) {
+ for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+ } else {
+ for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+ }
}
break;
}
@@ -4283,12 +4771,15 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (first) return stbi__err("first not IHDR", "Corrupt PNG");
if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+ if ((int)(ioff + c.length) < (int)ioff) return 0;
if (ioff + c.length > idata_limit) {
+ stbi__uint32 idata_limit_old = idata_limit;
stbi_uc *p;
if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
while (ioff + c.length > idata_limit)
idata_limit *= 2;
- p = (stbi_uc *) STBI_REALLOC(z->idata, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
+ STBI_NOTUSED(idata_limit_old);
+ p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
z->idata = p;
}
if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
@@ -4302,7 +4793,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (scan != STBI__SCAN_load) return 1;
if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
// initial guess for decoded data size to avoid unnecessary reallocs
- bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component
+ bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
if (z->expanded == NULL) return 0; // zlib should set error
@@ -4311,9 +4802,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
s->img_out_n = s->img_n+1;
else
s->img_out_n = s->img_n;
- if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
- if (has_trans)
- if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+ if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
+ if (has_trans) {
+ if (z->depth == 16) {
+ if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
+ } else {
+ if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+ }
+ }
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
stbi__de_iphone(z);
if (pal_img_n) {
@@ -4323,6 +4819,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (req_comp >= 3) s->img_out_n = req_comp;
if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
return 0;
+ } else if (has_trans) {
+ // non-paletted image with tRNS -> source image has (constant) alpha
+ ++s->img_n;
}
STBI_FREE(z->expanded); z->expanded = NULL;
return 1;
@@ -4350,21 +4849,28 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
}
}
-static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp)
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
{
- unsigned char *result=NULL;
+ void *result=NULL;
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+ if (p->depth < 8)
+ ri->bits_per_channel = 8;
+ else
+ ri->bits_per_channel = p->depth;
result = p->out;
p->out = NULL;
if (req_comp && req_comp != p->s->img_out_n) {
- result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+ if (ri->bits_per_channel == 8)
+ result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+ else
+ result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
p->s->img_out_n = req_comp;
if (result == NULL) return result;
}
*x = p->s->img_x;
*y = p->s->img_y;
- if (n) *n = p->s->img_out_n;
+ if (n) *n = p->s->img_n;
}
STBI_FREE(p->out); p->out = NULL;
STBI_FREE(p->expanded); p->expanded = NULL;
@@ -4373,11 +4879,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
return result;
}
-static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
stbi__png p;
p.s = s;
- return stbi__do_png(&p, x,y,comp,req_comp);
+ return stbi__do_png(&p, x,y,comp,req_comp, ri);
}
static int stbi__png_test(stbi__context *s)
@@ -4474,19 +4980,23 @@ static int stbi__shiftsigned(int v, int shift, int bits)
return result;
}
-static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+typedef struct
{
- stbi_uc *out;
- unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0;
- stbi_uc pal[256][4];
- int psize=0,i,j,compress=0,width;
- int bpp, flip_vertically, pad, target, offset, hsz;
+ int bpp, offset, hsz;
+ unsigned int mr,mg,mb,ma, all_a;
+} stbi__bmp_data;
+
+static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
+{
+ int hsz;
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
stbi__get32le(s); // discard filesize
stbi__get16le(s); // discard reserved
stbi__get16le(s); // discard reserved
- offset = stbi__get32le(s);
- hsz = stbi__get32le(s);
+ info->offset = stbi__get32le(s);
+ info->hsz = hsz = stbi__get32le(s);
+ info->mr = info->mg = info->mb = info->ma = 0;
+
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
if (hsz == 12) {
s->img_x = stbi__get16le(s);
@@ -4496,15 +5006,10 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
s->img_y = stbi__get32le(s);
}
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
- bpp = stbi__get16le(s);
- if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
- flip_vertically = ((int) s->img_y) > 0;
- s->img_y = abs((int) s->img_y);
- if (hsz == 12) {
- if (bpp < 24)
- psize = (offset - 14 - 24) / 3;
- } else {
- compress = stbi__get32le(s);
+ info->bpp = stbi__get16le(s);
+ if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
+ if (hsz != 12) {
+ int compress = stbi__get32le(s);
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
stbi__get32le(s); // discard sizeof
stbi__get32le(s); // discard hres
@@ -4518,27 +5023,25 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
stbi__get32le(s);
stbi__get32le(s);
}
- if (bpp == 16 || bpp == 32) {
- mr = mg = mb = 0;
+ if (info->bpp == 16 || info->bpp == 32) {
if (compress == 0) {
- if (bpp == 32) {
- mr = 0xffu << 16;
- mg = 0xffu << 8;
- mb = 0xffu << 0;
- ma = 0xffu << 24;
- fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255
- STBI_NOTUSED(fake_a);
+ if (info->bpp == 32) {
+ info->mr = 0xffu << 16;
+ info->mg = 0xffu << 8;
+ info->mb = 0xffu << 0;
+ info->ma = 0xffu << 24;
+ info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
} else {
- mr = 31u << 10;
- mg = 31u << 5;
- mb = 31u << 0;
+ info->mr = 31u << 10;
+ info->mg = 31u << 5;
+ info->mb = 31u << 0;
}
} else if (compress == 3) {
- mr = stbi__get32le(s);
- mg = stbi__get32le(s);
- mb = stbi__get32le(s);
+ info->mr = stbi__get32le(s);
+ info->mg = stbi__get32le(s);
+ info->mb = stbi__get32le(s);
// not documented, but generated by photoshop and handled by mspaint
- if (mr == mg && mg == mb) {
+ if (info->mr == info->mg && info->mg == info->mb) {
// ?!?!?
return stbi__errpuc("bad BMP", "bad BMP");
}
@@ -4546,11 +5049,13 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
return stbi__errpuc("bad BMP", "bad BMP");
}
} else {
- STBI_ASSERT(hsz == 108 || hsz == 124);
- mr = stbi__get32le(s);
- mg = stbi__get32le(s);
- mb = stbi__get32le(s);
- ma = stbi__get32le(s);
+ int i;
+ if (hsz != 108 && hsz != 124)
+ return stbi__errpuc("bad BMP", "bad BMP");
+ info->mr = stbi__get32le(s);
+ info->mg = stbi__get32le(s);
+ info->mb = stbi__get32le(s);
+ info->ma = stbi__get32le(s);
stbi__get32le(s); // discard color space
for (i=0; i < 12; ++i)
stbi__get32le(s); // discard color space parameters
@@ -4561,35 +5066,73 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
stbi__get32le(s); // discard reserved
}
}
- if (bpp < 16)
- psize = (offset - 14 - hsz) >> 2;
}
+ return (void *) 1;
+}
+
+
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+ stbi_uc *out;
+ unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
+ stbi_uc pal[256][4];
+ int psize=0,i,j,width;
+ int flip_vertically, pad, target;
+ stbi__bmp_data info;
+ STBI_NOTUSED(ri);
+
+ info.all_a = 255;
+ if (stbi__bmp_parse_header(s, &info) == NULL)
+ return NULL; // error code already set
+
+ flip_vertically = ((int) s->img_y) > 0;
+ s->img_y = abs((int) s->img_y);
+
+ mr = info.mr;
+ mg = info.mg;
+ mb = info.mb;
+ ma = info.ma;
+ all_a = info.all_a;
+
+ if (info.hsz == 12) {
+ if (info.bpp < 24)
+ psize = (info.offset - 14 - 24) / 3;
+ } else {
+ if (info.bpp < 16)
+ psize = (info.offset - 14 - info.hsz) >> 2;
+ }
+
s->img_n = ma ? 4 : 3;
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
target = req_comp;
else
target = s->img_n; // if they want monochrome, we'll post-convert
- out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
+
+ // sanity-check size
+ if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
+ return stbi__errpuc("too large", "Corrupt BMP");
+
+ out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory");
- if (bpp < 16) {
+ if (info.bpp < 16) {
int z=0;
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
for (i=0; i < psize; ++i) {
pal[i][2] = stbi__get8(s);
pal[i][1] = stbi__get8(s);
pal[i][0] = stbi__get8(s);
- if (hsz != 12) stbi__get8(s);
+ if (info.hsz != 12) stbi__get8(s);
pal[i][3] = 255;
}
- stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4));
- if (bpp == 4) width = (s->img_x + 1) >> 1;
- else if (bpp == 8) width = s->img_x;
+ stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
+ if (info.bpp == 4) width = (s->img_x + 1) >> 1;
+ else if (info.bpp == 8) width = s->img_x;
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
pad = (-width)&3;
for (j=0; j < (int) s->img_y; ++j) {
for (i=0; i < (int) s->img_x; i += 2) {
int v=stbi__get8(s),v2=0;
- if (bpp == 4) {
+ if (info.bpp == 4) {
v2 = v & 15;
v >>= 4;
}
@@ -4598,7 +5141,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
out[z++] = pal[v][2];
if (target == 4) out[z++] = 255;
if (i+1 == (int) s->img_x) break;
- v = (bpp == 8) ? stbi__get8(s) : v2;
+ v = (info.bpp == 8) ? stbi__get8(s) : v2;
out[z++] = pal[v][0];
out[z++] = pal[v][1];
out[z++] = pal[v][2];
@@ -4610,14 +5153,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0;
int easy=0;
- stbi__skip(s, offset - 14 - hsz);
- if (bpp == 24) width = 3 * s->img_x;
- else if (bpp == 16) width = 2*s->img_x;
+ stbi__skip(s, info.offset - 14 - info.hsz);
+ if (info.bpp == 24) width = 3 * s->img_x;
+ else if (info.bpp == 16) width = 2*s->img_x;
else /* bpp = 32 and pad = 0 */ width=0;
pad = (-width) & 3;
- if (bpp == 24) {
+ if (info.bpp == 24) {
easy = 1;
- } else if (bpp == 32) {
+ } else if (info.bpp == 32) {
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
easy = 2;
}
@@ -4638,22 +5181,31 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
out[z+0] = stbi__get8(s);
z += 3;
a = (easy == 2 ? stbi__get8(s) : 255);
+ all_a |= a;
if (target == 4) out[z++] = a;
}
} else {
+ int bpp = info.bpp;
for (i=0; i < (int) s->img_x; ++i) {
- stbi__uint32 v = (stbi__uint32) (bpp == 16 ? stbi__get16le(s) : stbi__get32le(s));
+ stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
int a;
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
+ all_a |= a;
if (target == 4) out[z++] = STBI__BYTECAST(a);
}
}
stbi__skip(s, pad);
}
}
+
+ // if alpha channel is all 0s, replace with all 255s
+ if (target == 4 && all_a == 0)
+ for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
+ out[i] = 255;
+
if (flip_vertically) {
stbi_uc t;
for (j=0; j < (int) s->img_y>>1; ++j) {
@@ -4680,20 +5232,55 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
// Targa Truevision - TGA
// by Jonathan Dummer
#ifndef STBI_NO_TGA
+// returns STBI_rgb or whatever, 0 on error
+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
+{
+ // only RGB or RGBA (incl. 16bit) or grey allowed
+ if(is_rgb16) *is_rgb16 = 0;
+ switch(bits_per_pixel) {
+ case 8: return STBI_grey;
+ case 16: if(is_grey) return STBI_grey_alpha;
+ // else: fall-through
+ case 15: if(is_rgb16) *is_rgb16 = 1;
+ return STBI_rgb;
+ case 24: // fall-through
+ case 32: return bits_per_pixel/8;
+ default: return 0;
+ }
+}
+
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
{
- int tga_w, tga_h, tga_comp;
- int sz;
+ int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
+ int sz, tga_colormap_type;
stbi__get8(s); // discard Offset
- sz = stbi__get8(s); // color type
- if( sz > 1 ) {
+ tga_colormap_type = stbi__get8(s); // colormap type
+ if( tga_colormap_type > 1 ) {
stbi__rewind(s);
return 0; // only RGB or indexed allowed
}
- sz = stbi__get8(s); // image type
- // only RGB or grey allowed, +/- RLE
- if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0;
- stbi__skip(s,9);
+ tga_image_type = stbi__get8(s); // image type
+ if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
+ if (tga_image_type != 1 && tga_image_type != 9) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s,4); // skip index of first colormap entry and number of entries
+ sz = stbi__get8(s); // check bits per palette color entry
+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
+ stbi__rewind(s);
+ return 0;
+ }
+ stbi__skip(s,4); // skip image x and y origin
+ tga_colormap_bpp = sz;
+ } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
+ if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
+ stbi__rewind(s);
+ return 0; // only RGB or grey allowed, +/- RLE
+ }
+ stbi__skip(s,9); // skip colormap specification and image x/y origin
+ tga_colormap_bpp = 0;
+ }
tga_w = stbi__get16le(s);
if( tga_w < 1 ) {
stbi__rewind(s);
@@ -4704,45 +5291,81 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
stbi__rewind(s);
return 0; // test height
}
- sz = stbi__get8(s); // bits per pixel
- // only RGB or RGBA or grey allowed
- if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) {
- stbi__rewind(s);
- return 0;
+ tga_bits_per_pixel = stbi__get8(s); // bits per pixel
+ stbi__get8(s); // ignore alpha bits
+ if (tga_colormap_bpp != 0) {
+ if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+ // when using a colormap, tga_bits_per_pixel is the size of the indexes
+ // I don't think anything but 8 or 16bit indexes makes sense
+ stbi__rewind(s);
+ return 0;
+ }
+ tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
+ } else {
+ tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
+ }
+ if(!tga_comp) {
+ stbi__rewind(s);
+ return 0;
}
- tga_comp = sz;
if (x) *x = tga_w;
if (y) *y = tga_h;
- if (comp) *comp = tga_comp / 8;
+ if (comp) *comp = tga_comp;
return 1; // seems to have passed everything
}
static int stbi__tga_test(stbi__context *s)
{
- int res;
- int sz;
+ int res = 0;
+ int sz, tga_color_type;
stbi__get8(s); // discard Offset
- sz = stbi__get8(s); // color type
- if ( sz > 1 ) return 0; // only RGB or indexed allowed
+ tga_color_type = stbi__get8(s); // color type
+ if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed
sz = stbi__get8(s); // image type
- if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE
- stbi__get16be(s); // discard palette start
- stbi__get16be(s); // discard palette length
- stbi__get8(s); // discard bits per palette color entry
- stbi__get16be(s); // discard x origin
- stbi__get16be(s); // discard y origin
- if ( stbi__get16be(s) < 1 ) return 0; // test width
- if ( stbi__get16be(s) < 1 ) return 0; // test height
+ if ( tga_color_type == 1 ) { // colormapped (paletted) image
+ if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
+ stbi__skip(s,4); // skip index of first colormap entry and number of entries
+ sz = stbi__get8(s); // check bits per palette color entry
+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+ stbi__skip(s,4); // skip image x and y origin
+ } else { // "normal" image w/o colormap
+ if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
+ stbi__skip(s,9); // skip colormap specification and image x/y origin
+ }
+ if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width
+ if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height
sz = stbi__get8(s); // bits per pixel
- if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) )
- res = 0;
- else
- res = 1;
+ if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+
+ res = 1; // if we got this far, everything's good and we can return 1 instead of 0
+
+errorEnd:
stbi__rewind(s);
return res;
}
-static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+// read 16bit value and convert to 24bit RGB
+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
+{
+ stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
+ stbi__uint16 fiveBitMask = 31;
+ // we have 3 channels with 5bits each
+ int r = (px >> 10) & fiveBitMask;
+ int g = (px >> 5) & fiveBitMask;
+ int b = px & fiveBitMask;
+ // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
+ out[0] = (stbi_uc)((r * 255)/31);
+ out[1] = (stbi_uc)((g * 255)/31);
+ out[2] = (stbi_uc)((b * 255)/31);
+
+ // some people claim that the most significant bit might be used for alpha
+ // (possibly if an alpha-bit is set in the "image descriptor byte")
+ // but that only made 16bit test images completely translucent..
+ // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
+}
+
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
// read in the TGA header stuff
int tga_offset = stbi__get8(s);
@@ -4757,16 +5380,18 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
int tga_width = stbi__get16le(s);
int tga_height = stbi__get16le(s);
int tga_bits_per_pixel = stbi__get8(s);
- int tga_comp = tga_bits_per_pixel / 8;
+ int tga_comp, tga_rgb16=0;
int tga_inverted = stbi__get8(s);
+ // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
// image data
unsigned char *tga_data;
unsigned char *tga_palette = NULL;
int i, j;
- unsigned char raw_data[4];
+ unsigned char raw_data[4] = {0};
int RLE_count = 0;
int RLE_repeating = 0;
int read_next_pixel = 1;
+ STBI_NOTUSED(ri);
// do a tiny bit of precessing
if ( tga_image_type >= 8 )
@@ -4774,41 +5399,33 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
tga_image_type -= 8;
tga_is_RLE = 1;
}
- /* int tga_alpha_bits = tga_inverted & 15; */
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
- // error check
- if ( //(tga_indexed) ||
- (tga_width < 1) || (tga_height < 1) ||
- (tga_image_type < 1) || (tga_image_type > 3) ||
- ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) &&
- (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
- )
- {
- return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA
- }
-
// If I'm paletted, then I'll use the number of bits from the palette
- if ( tga_indexed )
- {
- tga_comp = tga_palette_bits / 8;
- }
+ if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
+ else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
+
+ if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
+ return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
// tga info
*x = tga_width;
*y = tga_height;
if (comp) *comp = tga_comp;
- tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp );
+ if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
+ return stbi__errpuc("too large", "Corrupt TGA");
+
+ tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
// skip to the data's starting position (offset usually = 0)
stbi__skip(s, tga_offset );
- if ( !tga_indexed && !tga_is_RLE) {
+ if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
for (i=0; i < tga_height; ++i) {
- int y = tga_inverted ? tga_height -i - 1 : i;
- stbi_uc *tga_row = tga_data + y*tga_width*tga_comp;
+ int row = tga_inverted ? tga_height -i - 1 : i;
+ stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
stbi__getn(s, tga_row, tga_width * tga_comp);
}
} else {
@@ -4818,15 +5435,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
// any data to skip? (offset usually = 0)
stbi__skip(s, tga_palette_start );
// load the palette
- tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 );
+ tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
if (!tga_palette) {
STBI_FREE(tga_data);
return stbi__errpuc("outofmem", "Out of memory");
}
- if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) {
- STBI_FREE(tga_data);
- STBI_FREE(tga_palette);
- return stbi__errpuc("bad palette", "Corrupt TGA");
+ if (tga_rgb16) {
+ stbi_uc *pal_entry = tga_palette;
+ STBI_ASSERT(tga_comp == STBI_rgb);
+ for (i=0; i < tga_palette_len; ++i) {
+ stbi__tga_read_rgb16(s, pal_entry);
+ pal_entry += tga_comp;
+ }
+ } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
+ STBI_FREE(tga_data);
+ STBI_FREE(tga_palette);
+ return stbi__errpuc("bad palette", "Corrupt TGA");
}
}
// load the data
@@ -4856,23 +5480,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
// load however much data we did have
if ( tga_indexed )
{
- // read in 1 byte, then perform the lookup
- int pal_idx = stbi__get8(s);
- if ( pal_idx >= tga_palette_len )
- {
- // invalid index
+ // read in index, then perform the lookup
+ int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
+ if ( pal_idx >= tga_palette_len ) {
+ // invalid index
pal_idx = 0;
}
- pal_idx *= tga_bits_per_pixel / 8;
- for (j = 0; j*8 < tga_bits_per_pixel; ++j)
- {
+ pal_idx *= tga_comp;
+ for (j = 0; j < tga_comp; ++j) {
raw_data[j] = tga_palette[pal_idx+j];
}
- } else
- {
+ } else if(tga_rgb16) {
+ STBI_ASSERT(tga_comp == STBI_rgb);
+ stbi__tga_read_rgb16(s, raw_data);
+ } else {
// read in the data raw
- for (j = 0; j*8 < tga_bits_per_pixel; ++j)
- {
+ for (j = 0; j < tga_comp; ++j) {
raw_data[j] = stbi__get8(s);
}
}
@@ -4911,8 +5534,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
}
}
- // swap RGB
- if (tga_comp >= 3)
+ // swap RGB - if the source data was RGB16, it already is in the right order
+ if (tga_comp >= 3 && !tga_rgb16)
{
unsigned char* tga_pixel = tga_data;
for (i=0; i < tga_width * tga_height; ++i)
@@ -4948,13 +5571,53 @@ static int stbi__psd_test(stbi__context *s)
return r;
}
-static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
{
- int pixelCount;
+ int count, nleft, len;
+
+ count = 0;
+ while ((nleft = pixelCount - count) > 0) {
+ len = stbi__get8(s);
+ if (len == 128) {
+ // No-op.
+ } else if (len < 128) {
+ // Copy next len+1 bytes literally.
+ len++;
+ if (len > nleft) return 0; // corrupt data
+ count += len;
+ while (len) {
+ *p = stbi__get8(s);
+ p += 4;
+ len--;
+ }
+ } else if (len > 128) {
+ stbi_uc val;
+ // Next -len+1 bytes in the dest are replicated from next source byte.
+ // (Interpret len as a negative 8-bit int.)
+ len = 257 - len;
+ if (len > nleft) return 0; // corrupt data
+ val = stbi__get8(s);
+ count += len;
+ while (len) {
+ *p = val;
+ p += 4;
+ len--;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+ int pixelCount;
int channelCount, compression;
- int channel, i, count, len;
+ int channel, i;
+ int bitdepth;
int w,h;
stbi_uc *out;
+ STBI_NOTUSED(ri);
// Check identifier
if (stbi__get32be(s) != 0x38425053) // "8BPS"
@@ -4977,8 +5640,9 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
w = stbi__get32be(s);
// Make sure the depth is 8 bits.
- if (stbi__get16be(s) != 8)
- return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 bit");
+ bitdepth = stbi__get16be(s);
+ if (bitdepth != 8 && bitdepth != 16)
+ return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
// Make sure the color mode is RGB.
// Valid options are:
@@ -5010,8 +5674,18 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
if (compression > 1)
return stbi__errpuc("bad compression", "PSD has an unknown compression format");
+ // Check size
+ if (!stbi__mad3sizes_valid(4, w, h, 0))
+ return stbi__errpuc("too large", "Corrupt PSD");
+
// Create the destination image.
- out = (stbi_uc *) stbi__malloc(4 * w*h);
+
+ if (!compression && bitdepth == 16 && bpc == 16) {
+ out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
+ ri->bits_per_channel = 16;
+ } else
+ out = (stbi_uc *) stbi__malloc(4 * w*h);
+
if (!out) return stbi__errpuc("outofmem", "Out of memory");
pixelCount = w*h;
@@ -5039,67 +5713,94 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
p = out+channel;
if (channel >= channelCount) {
// Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = (channel == 3 ? 255 : 0);
} else {
// Read the RLE data.
- count = 0;
- while (count < pixelCount) {
- len = stbi__get8(s);
- if (len == 128) {
- // No-op.
- } else if (len < 128) {
- // Copy next len+1 bytes literally.
- len++;
- count += len;
- while (len) {
- *p = stbi__get8(s);
- p += 4;
- len--;
- }
- } else if (len > 128) {
- stbi_uc val;
- // Next -len+1 bytes in the dest are replicated from next source byte.
- // (Interpret len as a negative 8-bit int.)
- len ^= 0x0FF;
- len += 2;
- val = stbi__get8(s);
- count += len;
- while (len) {
- *p = val;
- p += 4;
- len--;
- }
- }
+ if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+ STBI_FREE(out);
+ return stbi__errpuc("corrupt", "bad RLE data");
}
}
}
} else {
// We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
- // where each channel consists of an 8-bit value for each pixel in the image.
+ // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
// Read the data by channel.
for (channel = 0; channel < 4; channel++) {
- stbi_uc *p;
-
- p = out + channel;
- if (channel > channelCount) {
+ if (channel >= channelCount) {
// Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4;
+ if (bitdepth == 16 && bpc == 16) {
+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+ stbi__uint16 val = channel == 3 ? 65535 : 0;
+ for (i = 0; i < pixelCount; i++, q += 4)
+ *q = val;
+ } else {
+ stbi_uc *p = out+channel;
+ stbi_uc val = channel == 3 ? 255 : 0;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = val;
+ }
} else {
- // Read the data.
- for (i = 0; i < pixelCount; i++)
- *p = stbi__get8(s), p += 4;
+ if (ri->bits_per_channel == 16) { // output bpc
+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+ for (i = 0; i < pixelCount; i++, q += 4)
+ *q = (stbi__uint16) stbi__get16be(s);
+ } else {
+ stbi_uc *p = out+channel;
+ if (bitdepth == 16) { // input bpc
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = (stbi_uc) (stbi__get16be(s) >> 8);
+ } else {
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = stbi__get8(s);
+ }
+ }
}
}
}
+ // remove weird white matte from PSD
+ if (channelCount >= 4) {
+ if (ri->bits_per_channel == 16) {
+ for (i=0; i < w*h; ++i) {
+ stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
+ if (pixel[3] != 0 && pixel[3] != 65535) {
+ float a = pixel[3] / 65535.0f;
+ float ra = 1.0f / a;
+ float inv_a = 65535.0f * (1 - ra);
+ pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
+ pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
+ pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
+ }
+ }
+ } else {
+ for (i=0; i < w*h; ++i) {
+ unsigned char *pixel = out + 4*i;
+ if (pixel[3] != 0 && pixel[3] != 255) {
+ float a = pixel[3] / 255.0f;
+ float ra = 1.0f / a;
+ float inv_a = 255.0f * (1 - ra);
+ pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
+ pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
+ pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
+ }
+ }
+ }
+ }
+
+ // convert to desired output format
if (req_comp && req_comp != 4) {
- out = stbi__convert_format(out, 4, req_comp, w, h);
+ if (ri->bits_per_channel == 16)
+ out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
+ else
+ out = stbi__convert_format(out, 4, req_comp, w, h);
if (out == NULL) return out; // stbi__convert_format frees input on failure
}
- if (comp) *comp = channelCount;
+ if (comp) *comp = 4;
*y = h;
*x = w;
@@ -5247,7 +5948,6 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c
if (count >= 128) { // Repeated
stbi_uc value[4];
- int i;
if (count==128)
count = stbi__get16be(s);
@@ -5280,10 +5980,13 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c
return result;
}
-static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp)
+static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
{
stbi_uc *result;
- int i, x,y;
+ int i, x,y, internal_comp;
+ STBI_NOTUSED(ri);
+
+ if (!comp) comp = &internal_comp;
for (i=0; i<92; ++i)
stbi__get8(s);
@@ -5291,14 +5994,14 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re
x = stbi__get16be(s);
y = stbi__get16be(s);
if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
- if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode");
+ if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
stbi__get32be(s); //skip `ratio'
stbi__get16be(s); //skip `fields'
stbi__get16be(s); //skip `pad'
// intermediate buffer is RGBA
- result = (stbi_uc *) stbi__malloc(x*y*4);
+ result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
memset(result, 0xff, x*y*4);
if (!stbi__pic_load_core(s,x,y,comp, result)) {
@@ -5335,8 +6038,8 @@ typedef struct
typedef struct
{
int w,h;
- stbi_uc *out; // output buffer (always 4 components)
- int flags, bgindex, ratio, transparent, eflags;
+ stbi_uc *out, *old_out; // output buffer (always 4 components)
+ int flags, bgindex, ratio, transparent, eflags, delay;
stbi_uc pal[256][4];
stbi_uc lpal[256][4];
stbi__gif_lzw codes[4096];
@@ -5407,13 +6110,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
{
- stbi__gif g;
- if (!stbi__gif_header(s, &g, comp, 1)) {
+ stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+ if (!stbi__gif_header(s, g, comp, 1)) {
+ STBI_FREE(g);
stbi__rewind( s );
return 0;
}
- if (x) *x = g.w;
- if (y) *y = g.h;
+ if (x) *x = g->w;
+ if (y) *y = g->h;
+ STBI_FREE(g);
return 1;
}
@@ -5454,22 +6159,23 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
{
stbi_uc lzw_cs;
- stbi__int32 len, code;
+ stbi__int32 len, init_code;
stbi__uint32 first;
stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
stbi__gif_lzw *p;
lzw_cs = stbi__get8(s);
+ if (lzw_cs > 12) return NULL;
clear = 1 << lzw_cs;
first = 1;
codesize = lzw_cs + 1;
codemask = (1 << codesize) - 1;
bits = 0;
valid_bits = 0;
- for (code = 0; code < clear; code++) {
- g->codes[code].prefix = -1;
- g->codes[code].first = (stbi_uc) code;
- g->codes[code].suffix = (stbi_uc) code;
+ for (init_code = 0; init_code < clear; init_code++) {
+ g->codes[init_code].prefix = -1;
+ g->codes[init_code].first = (stbi_uc) init_code;
+ g->codes[init_code].suffix = (stbi_uc) init_code;
}
// support no starting clear code
@@ -5530,17 +6236,18 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
}
}
-static void stbi__fill_gif_background(stbi__gif *g)
+static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1)
{
- int i;
+ int x, y;
stbi_uc *c = g->pal[g->bgindex];
- // @OPTIMIZE: write a dword at a time
- for (i = 0; i < g->w * g->h * 4; i += 4) {
- stbi_uc *p = &g->out[i];
- p[0] = c[2];
- p[1] = c[1];
- p[2] = c[0];
- p[3] = c[3];
+ for (y = y0; y < y1; y += 4 * g->w) {
+ for (x = x0; x < x1; x += 4) {
+ stbi_uc *p = &g->out[y + x];
+ p[0] = c[2];
+ p[1] = c[1];
+ p[2] = c[0];
+ p[3] = 0;
+ }
}
}
@@ -5548,27 +6255,43 @@ static void stbi__fill_gif_background(stbi__gif *g)
static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp)
{
int i;
- stbi_uc *old_out = 0;
+ stbi_uc *prev_out = 0;
- if (g->out == 0) {
- if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
- g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
- if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
- stbi__fill_gif_background(g);
- } else {
- // animated-gif-only path
- if (((g->eflags & 0x1C) >> 2) == 3) {
- old_out = g->out;
- g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
- if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
- memcpy(g->out, old_out, g->w*g->h*4);
- }
+ if (g->out == 0 && !stbi__gif_header(s, g, comp,0))
+ return 0; // stbi__g_failure_reason set by stbi__gif_header
+
+ if (!stbi__mad3sizes_valid(g->w, g->h, 4, 0))
+ return stbi__errpuc("too large", "GIF too large");
+
+ prev_out = g->out;
+ g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0);
+ if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
+
+ switch ((g->eflags & 0x1C) >> 2) {
+ case 0: // unspecified (also always used on 1st frame)
+ stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h);
+ break;
+ case 1: // do not dispose
+ if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h);
+ g->old_out = prev_out;
+ break;
+ case 2: // dispose to background
+ if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h);
+ stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y);
+ break;
+ case 3: // dispose to previous
+ if (g->old_out) {
+ for (i = g->start_y; i < g->max_y; i += 4 * g->w)
+ memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x);
+ }
+ break;
}
for (;;) {
switch (stbi__get8(s)) {
case 0x2C: /* Image Descriptor */
{
+ int prev_trans = -1;
stbi__int32 x, y, w, h;
stbi_uc *o;
@@ -5601,10 +6324,10 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
g->color_table = (stbi_uc *) g->lpal;
} else if (g->flags & 0x80) {
- for (i=0; i < 256; ++i) // @OPTIMIZE: stbi__jpeg_reset only the previous transparent
- g->pal[i][3] = 255;
- if (g->transparent >= 0 && (g->eflags & 0x01))
+ if (g->transparent >= 0 && (g->eflags & 0x01)) {
+ prev_trans = g->pal[g->transparent][3];
g->pal[g->transparent][3] = 0;
+ }
g->color_table = (stbi_uc *) g->pal;
} else
return stbi__errpuc("missing color table", "Corrupt GIF");
@@ -5612,8 +6335,9 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
o = stbi__process_gif_raster(s, g);
if (o == NULL) return NULL;
- if (req_comp && req_comp != 4)
- o = stbi__convert_format(o, 4, req_comp, g->w, g->h);
+ if (prev_trans != -1)
+ g->pal[g->transparent][3] = (stbi_uc) prev_trans;
+
return o;
}
@@ -5624,7 +6348,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
len = stbi__get8(s);
if (len == 4) {
g->eflags = stbi__get8(s);
- stbi__get16le(s); // delay
+ g->delay = stbi__get16le(s);
g->transparent = stbi__get8(s);
} else {
stbi__skip(s, len);
@@ -5643,21 +6367,28 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
return stbi__errpuc("unknown code", "Corrupt GIF");
}
}
+
+ STBI_NOTUSED(req_comp);
}
-static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
stbi_uc *u = 0;
- stbi__gif g;
- memset(&g, 0, sizeof(g));
+ stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+ memset(g, 0, sizeof(*g));
+ STBI_NOTUSED(ri);
- u = stbi__gif_load_next(s, &g, comp, req_comp);
+ u = stbi__gif_load_next(s, g, comp, req_comp);
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
if (u) {
- *x = g.w;
- *y = g.h;
+ *x = g->w;
+ *y = g->h;
+ if (req_comp && req_comp != 4)
+ u = stbi__convert_format(u, 4, req_comp, g->w, g->h);
}
-
+ else if (g->out)
+ STBI_FREE(g->out);
+ STBI_FREE(g);
return u;
}
@@ -5671,20 +6402,24 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
// Radiance RGBE HDR loader
// originally by Nicolas Schulz
#ifndef STBI_NO_HDR
-static int stbi__hdr_test_core(stbi__context *s)
+static int stbi__hdr_test_core(stbi__context *s, const char *signature)
{
- const char *signature = "#?RADIANCE\n";
int i;
for (i=0; signature[i]; ++i)
if (stbi__get8(s) != signature[i])
- return 0;
+ return 0;
+ stbi__rewind(s);
return 1;
}
static int stbi__hdr_test(stbi__context* s)
{
- int r = stbi__hdr_test_core(s);
+ int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
stbi__rewind(s);
+ if(!r) {
+ r = stbi__hdr_test_core(s, "#?RGBE\n");
+ stbi__rewind(s);
+ }
return r;
}
@@ -5738,7 +6473,7 @@ static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
}
}
-static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
char buffer[STBI__HDR_BUFLEN];
char *token;
@@ -5749,10 +6484,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
int len;
unsigned char count, value;
int i, j, k, c1,c2, z;
-
+ const char *headerToken;
+ STBI_NOTUSED(ri);
// Check identifier
- if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0)
+ headerToken = stbi__hdr_gettoken(s,buffer);
+ if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
return stbi__errpf("not HDR", "Corrupt HDR image");
// Parse header
@@ -5781,8 +6518,13 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
if (comp) *comp = 3;
if (req_comp == 0) req_comp = 3;
+ if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
+ return stbi__errpf("too large", "HDR image is too large");
+
// Read data
- hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float));
+ hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
+ if (!hdr_data)
+ return stbi__errpf("outofmem", "Out of memory");
// Load image data
// image data is stored as some number of sca
@@ -5821,20 +6563,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
len <<= 8;
len |= stbi__get8(s);
if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
- if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4);
+ if (scanline == NULL) {
+ scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
+ if (!scanline) {
+ STBI_FREE(hdr_data);
+ return stbi__errpf("outofmem", "Out of memory");
+ }
+ }
for (k = 0; k < 4; ++k) {
+ int nleft;
i = 0;
- while (i < width) {
+ while ((nleft = width - i) > 0) {
count = stbi__get8(s);
if (count > 128) {
// Run
value = stbi__get8(s);
count -= 128;
+ if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = value;
} else {
// Dump
+ if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = stbi__get8(s);
}
@@ -5843,7 +6594,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
for (i=0; i < width; ++i)
stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
}
- STBI_FREE(scanline);
+ if (scanline)
+ STBI_FREE(scanline);
}
return hdr_data;
@@ -5854,8 +6606,13 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
char buffer[STBI__HDR_BUFLEN];
char *token;
int valid = 0;
+ int dummy;
- if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) {
+ if (!x) x = &dummy;
+ if (!y) y = &dummy;
+ if (!comp) comp = &dummy;
+
+ if (stbi__hdr_test(s) == 0) {
stbi__rewind( s );
return 0;
}
@@ -5892,29 +6649,17 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
#ifndef STBI_NO_BMP
static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
{
- int hsz;
- if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') {
- stbi__rewind( s );
- return 0;
- }
- stbi__skip(s,12);
- hsz = stbi__get32le(s);
- if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) {
- stbi__rewind( s );
- return 0;
- }
- if (hsz == 12) {
- *x = stbi__get16le(s);
- *y = stbi__get16le(s);
- } else {
- *x = stbi__get32le(s);
- *y = stbi__get32le(s);
- }
- if (stbi__get16le(s) != 1) {
- stbi__rewind( s );
- return 0;
- }
- *comp = stbi__get16le(s) / 8;
+ void *p;
+ stbi__bmp_data info;
+
+ info.all_a = 255;
+ p = stbi__bmp_parse_header(s, &info);
+ stbi__rewind( s );
+ if (p == NULL)
+ return 0;
+ if (x) *x = s->img_x;
+ if (y) *y = s->img_y;
+ if (comp) *comp = info.ma ? 4 : 3;
return 1;
}
#endif
@@ -5922,7 +6667,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
#ifndef STBI_NO_PSD
static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
{
- int channelCount;
+ int channelCount, dummy;
+ if (!x) x = &dummy;
+ if (!y) y = &dummy;
+ if (!comp) comp = &dummy;
if (stbi__get32be(s) != 0x38425053) {
stbi__rewind( s );
return 0;
@@ -5955,17 +6703,29 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
#ifndef STBI_NO_PIC
static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
{
- int act_comp=0,num_packets=0,chained;
+ int act_comp=0,num_packets=0,chained,dummy;
stbi__pic_packet packets[10];
- stbi__skip(s, 92);
+ if (!x) x = &dummy;
+ if (!y) y = &dummy;
+ if (!comp) comp = &dummy;
+
+ if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
+ stbi__rewind(s);
+ return 0;
+ }
+
+ stbi__skip(s, 88);
*x = stbi__get16be(s);
*y = stbi__get16be(s);
- if (stbi__at_eof(s)) return 0;
+ if (stbi__at_eof(s)) {
+ stbi__rewind( s);
+ return 0;
+ }
if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
- stbi__rewind( s );
- return 0;
+ stbi__rewind( s );
+ return 0;
}
stbi__skip(s, 8);
@@ -6025,16 +6785,22 @@ static int stbi__pnm_test(stbi__context *s)
return 1;
}
-static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
stbi_uc *out;
+ STBI_NOTUSED(ri);
+
if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
return 0;
+
*x = s->img_x;
*y = s->img_y;
- *comp = s->img_n;
+ if (comp) *comp = s->img_n;
- out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y);
+ if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+ return stbi__errpuc("too large", "PNM too large");
+
+ out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory");
stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
@@ -6052,8 +6818,16 @@ static int stbi__pnm_isspace(char c)
static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)
{
- while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
- *c = (char) stbi__get8(s);
+ for (;;) {
+ while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
+ *c = (char) stbi__get8(s);
+
+ if (stbi__at_eof(s) || *c != '#')
+ break;
+
+ while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
+ *c = (char) stbi__get8(s);
+ }
}
static int stbi__pnm_isdigit(char c)
@@ -6075,16 +6849,20 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c)
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
{
- int maxv;
+ int maxv, dummy;
char c, p, t;
- stbi__rewind( s );
+ if (!x) x = &dummy;
+ if (!y) y = &dummy;
+ if (!comp) comp = &dummy;
+
+ stbi__rewind(s);
// Get identifier
p = (char) stbi__get8(s);
t = (char) stbi__get8(s);
if (p != 'P' || (t != '5' && t != '6')) {
- stbi__rewind( s );
+ stbi__rewind(s);
return 0;
}
@@ -6191,6 +6969,45 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
/*
revision history:
+ 2.16 (2017-07-23) all functions have 16-bit variants;
+ STBI_NO_STDIO works again;
+ compilation fixes;
+ fix rounding in unpremultiply;
+ optimize vertical flip;
+ disable raw_len validation;
+ documentation fixes
+ 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
+ warning fixes; disable run-time SSE detection on gcc;
+ uniform handling of optional "return" values;
+ thread-safe initialization of zlib tables
+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+ 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+ 2.11 (2016-04-02) allocate large structures on the stack
+ remove white matting for transparent PSD
+ fix reported channel count for PNG & BMP
+ re-enable SSE2 in non-gcc 64-bit
+ support RGB-formatted JPEG
+ read 16-bit PNGs (only as 8-bit)
+ 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
+ 2.09 (2016-01-16) allow comments in PNM files
+ 16-bit-per-pixel TGA (not bit-per-component)
+ info() for TGA could break due to .hdr handling
+ info() for BMP to shares code instead of sloppy parse
+ can use STBI_REALLOC_SIZED if allocator doesn't support realloc
+ code cleanup
+ 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
+ 2.07 (2015-09-13) fix compiler warnings
+ partial animated GIF support
+ limited 16-bpc PSD support
+ #ifdef unused functions
+ bug with < 92 byte PIC,PNM,HDR,TGA
+ 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
+ 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
+ 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
+ 2.03 (2015-04-12) extra corruption checking (mmozeiko)
+ stbi_set_flip_vertically_on_load (nguillemot)
+ fix NEON support; fix mingw support
2.02 (2015-01-19) fix incorrect assert, fix warning
2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
@@ -6277,7 +7094,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
1.21 fix use of 'stbi_uc' in header (reported by jon blow)
1.20 added support for Softimage PIC, by Tom Seddon
1.19 bug in interlaced PNG corruption check (found by ryg)
- 1.18 2008-08-02
+ 1.18 (2008-08-02)
fix a threading bug (local mutable static)
1.17 support interlaced PNG
1.16 major bugfix - stbi__convert_format converted one too many pixels
@@ -6322,5 +7139,49 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
0.51 obey req_comp requests, 1-component jpegs return as 1-component,
on 'test' only check type, not whether we support this variant
- 0.50 first released version
+ 0.50 (2006-11-19)
+ first released version
+*/
+
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
*/
diff --git a/extlibs/headers/stb_image/stb_image_write.h b/extlibs/headers/stb_image/stb_image_write.h
index 5a449d9..9d553e0 100644
--- a/extlibs/headers/stb_image/stb_image_write.h
+++ b/extlibs/headers/stb_image/stb_image_write.h
@@ -1,7 +1,6 @@
-/* stb_image_write - v0.97 - public domain - http://nothings.org/stb/stb_image_write.h
- writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
- no warranty implied; use at your own risk
-
+/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h
+ writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
+ no warranty implied; use at your own risk
Before #including,
@@ -9,7 +8,6 @@
in the file that you want to have the implementation.
-
Will probably not work correctly with strict-aliasing optimizations.
ABOUT:
@@ -19,9 +17,16 @@ ABOUT:
The PNG output is not optimal; it is 20-50% larger than the file
written by a decent optimizing implementation. This library is designed
- for source code compactness and simplicitly, not optimal image file size
+ for source code compactness and simplicity, not optimal image file size
or run-time performance.
+BUILDING:
+
+ You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
+ You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
+ malloc,realloc,free.
+ You can define STBIW_MEMMOVE() to replace memmove()
+
USAGE:
There are four functions, one for each image file format:
@@ -29,10 +34,27 @@ USAGE:
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
- int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
+ int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+ int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data);
+
+ There are also four equivalent functions that use an arbitrary write function. You are
+ expected to open/close your file-equivalent before and after calling these:
+
+ int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
+ int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+ int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
+ int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
+
+ where the callback is:
+ void stbi_write_func(void *context, void *data, int size);
+
+ You can define STBI_WRITE_NO_STDIO to disable the file variant of these
+ functions, so the library will not use stdio.h at all. However, this will
+ also disable HDR writing, because it requires stdio for formatted output.
Each function returns 0 on failure and non-0 on success.
-
+
The functions create an image file defined by the parameters. The image
is a rectangle of pixels stored from left-to-right, top-to-bottom.
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
@@ -45,7 +67,7 @@ USAGE:
PNG creates output files with the same number of components as the input.
The BMP format expands Y to RGB in the file format and does not
output alpha.
-
+
PNG supports writing rectangles of data even when the bytes storing rows of
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
by supplying the stride between the beginning of adjacent rows. The other
@@ -57,6 +79,13 @@ USAGE:
data, alpha (if provided) is discarded, and for monochrome data it is
replicated across all three channels.
+ TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
+ data, set the global variable 'stbi_write_tga_with_rle' to 0.
+
+ JPEG does ignore alpha channels in input data; quality is between 1 and 100.
+ Higher quality looks better but results in a bigger image.
+ JPEG baseline (no JPEG progressive).
+
CREDITS:
PNG/BMP/TGA
@@ -65,8 +94,31 @@ CREDITS:
Baldur Karlsson
TGA monochrome:
Jean-Sebastien Guay
- Bugfixes:
- Chribba@github
+ misc enhancements:
+ Tim Kelsey
+ TGA RLE
+ Alan Hickman
+ initial file IO callback implementation
+ Emmanuel Julien
+ JPEG
+ Jon Olick (original jo_jpeg.cpp code)
+ Daniel Gibson
+ bugfixes:
+ github:Chribba
+ Guillaume Chereau
+ github:jry2
+ github:romigrou
+ Sergio Gonzalez
+ Jonas Karlsson
+ Filip Wasil
+ Thatcher Ulrich
+ github:poppolopoppo
+ Patrick Boettcher
+
+LICENSE
+
+ See end of file for license information.
+
*/
#ifndef INCLUDE_STB_IMAGE_WRITE_H
@@ -76,10 +128,28 @@ CREDITS:
extern "C" {
#endif
-extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
-extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
-extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
-extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+#ifdef STB_IMAGE_WRITE_STATIC
+#define STBIWDEF static
+#else
+#define STBIWDEF extern
+extern int stbi_write_tga_with_rle;
+#endif
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
+STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
+#endif
+
+typedef void stbi_write_func(void *context, void *data, int size);
+
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
+STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
#ifdef __cplusplus
}
@@ -89,53 +159,189 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
+#ifdef _WIN32
+ #ifndef _CRT_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_WARNINGS
+ #endif
+ #ifndef _CRT_NONSTDC_NO_DEPRECATE
+ #define _CRT_NONSTDC_NO_DEPRECATE
+ #endif
+#endif
+
+#ifndef STBI_WRITE_NO_STDIO
+#include <stdio.h>
+#endif // STBI_WRITE_NO_STDIO
+
#include <stdarg.h>
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
-#include <assert.h>
#include <math.h>
+#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
+// ok
+#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
+// ok
+#else
+#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
+#endif
+
+#ifndef STBIW_MALLOC
+#define STBIW_MALLOC(sz) malloc(sz)
+#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
+#define STBIW_FREE(p) free(p)
+#endif
+
+#ifndef STBIW_REALLOC_SIZED
+#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
+#endif
+
+
+#ifndef STBIW_MEMMOVE
+#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
+#endif
+
+
+#ifndef STBIW_ASSERT
+#include <assert.h>
+#define STBIW_ASSERT(x) assert(x)
+#endif
+
+#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
+
+typedef struct
+{
+ stbi_write_func *func;
+ void *context;
+} stbi__write_context;
+
+// initialize a callback-based context
+static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
+{
+ s->func = c;
+ s->context = context;
+}
+
+#ifndef STBI_WRITE_NO_STDIO
+
+static void stbi__stdio_write(void *context, void *data, int size)
+{
+ fwrite(data,1,size,(FILE*) context);
+}
+
+static int stbi__start_write_file(stbi__write_context *s, const char *filename)
+{
+ FILE *f = fopen(filename, "wb");
+ stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
+ return f != NULL;
+}
+
+static void stbi__end_write_file(stbi__write_context *s)
+{
+ fclose((FILE *)s->context);
+}
+
+#endif // !STBI_WRITE_NO_STDIO
+
typedef unsigned int stbiw_uint32;
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
-static void writefv(FILE *f, const char *fmt, va_list v)
+#ifdef STB_IMAGE_WRITE_STATIC
+static int stbi_write_tga_with_rle = 1;
+#else
+int stbi_write_tga_with_rle = 1;
+#endif
+
+static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
{
while (*fmt) {
switch (*fmt++) {
case ' ': break;
- case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
- case '2': { int x = va_arg(v,int); unsigned char b[2];
- b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
- fwrite(b,2,1,f); break; }
- case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
- b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
- b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
- fwrite(b,4,1,f); break; }
+ case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
+ s->func(s->context,&x,1);
+ break; }
+ case '2': { int x = va_arg(v,int);
+ unsigned char b[2];
+ b[0] = STBIW_UCHAR(x);
+ b[1] = STBIW_UCHAR(x>>8);
+ s->func(s->context,b,2);
+ break; }
+ case '4': { stbiw_uint32 x = va_arg(v,int);
+ unsigned char b[4];
+ b[0]=STBIW_UCHAR(x);
+ b[1]=STBIW_UCHAR(x>>8);
+ b[2]=STBIW_UCHAR(x>>16);
+ b[3]=STBIW_UCHAR(x>>24);
+ s->func(s->context,b,4);
+ break; }
default:
- assert(0);
+ STBIW_ASSERT(0);
return;
}
}
}
-static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
+static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
+{
+ va_list v;
+ va_start(v, fmt);
+ stbiw__writefv(s, fmt, v);
+ va_end(v);
+}
+
+static void stbiw__putc(stbi__write_context *s, unsigned char c)
+{
+ s->func(s->context, &c, 1);
+}
+
+static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
{
unsigned char arr[3];
arr[0] = a, arr[1] = b, arr[2] = c;
- fwrite(arr, 3, 1, f);
+ s->func(s->context, arr, 3);
}
-static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
+static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
{
unsigned char bg[3] = { 255, 0, 255}, px[3];
+ int k;
+
+ if (write_alpha < 0)
+ s->func(s->context, &d[comp - 1], 1);
+
+ switch (comp) {
+ case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
+ case 1:
+ if (expand_mono)
+ stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
+ else
+ s->func(s->context, d, 1); // monochrome TGA
+ break;
+ case 4:
+ if (!write_alpha) {
+ // composite against pink background
+ for (k = 0; k < 3; ++k)
+ px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
+ stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
+ break;
+ }
+ /* FALLTHROUGH */
+ case 3:
+ stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
+ break;
+ }
+ if (write_alpha > 0)
+ s->func(s->context, &d[comp - 1], 1);
+}
+
+static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
+{
stbiw_uint32 zero = 0;
- int i,j,k, j_end;
+ int i,j, j_end;
if (y <= 0)
return;
- if (vdir < 0)
+ if (vdir < 0)
j_end = -1, j = y-1;
else
j_end = y, j = 0;
@@ -143,73 +349,147 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp,
for (; j != j_end; j += vdir) {
for (i=0; i < x; ++i) {
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
- if (write_alpha < 0)
- fwrite(&d[comp-1], 1, 1, f);
- switch (comp) {
- case 1: fwrite(d, 1, 1, f);
- break;
- case 2: if (expand_mono)
- write3(f, d[0],d[0],d[0]); // monochrome bmp
- else
- fwrite(d, 1, 1, f); // monochrome TGA
- break;
- case 4:
- if (!write_alpha) {
- // composite against pink background
- for (k=0; k < 3; ++k)
- px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
- write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
- break;
- }
- /* FALLTHROUGH */
- case 3:
- write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
- break;
- }
- if (write_alpha > 0)
- fwrite(&d[comp-1], 1, 1, f);
+ stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
}
- fwrite(&zero,scanline_pad,1,f);
+ s->func(s->context, &zero, scanline_pad);
}
}
-static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
+static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
{
- FILE *f;
- if (y < 0 || x < 0) return 0;
- f = fopen(filename, "wb");
- if (f) {
+ if (y < 0 || x < 0) {
+ return 0;
+ } else {
va_list v;
va_start(v, fmt);
- writefv(f, fmt, v);
+ stbiw__writefv(s, fmt, v);
va_end(v);
- write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
- fclose(f);
+ stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
+ return 1;
}
- return f != NULL;
}
-int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
+static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
- return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
+ return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
}
-int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
+{
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_bmp_core(&s, x, y, comp, data);
+}
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
+{
+ stbi__write_context s;
+ if (stbi__start_write_file(&s,filename)) {
+ int r = stbi_write_bmp_core(&s, x, y, comp, data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
+}
+#endif //!STBI_WRITE_NO_STDIO
+
+static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
{
int has_alpha = (comp == 2 || comp == 4);
int colorbytes = has_alpha ? comp-1 : comp;
int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
- return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
- "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
+
+ if (y < 0 || x < 0)
+ return 0;
+
+ if (!stbi_write_tga_with_rle) {
+ return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
+ "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
+ } else {
+ int i,j,k;
+
+ stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
+
+ for (j = y - 1; j >= 0; --j) {
+ unsigned char *row = (unsigned char *) data + j * x * comp;
+ int len;
+
+ for (i = 0; i < x; i += len) {
+ unsigned char *begin = row + i * comp;
+ int diff = 1;
+ len = 1;
+
+ if (i < x - 1) {
+ ++len;
+ diff = memcmp(begin, row + (i + 1) * comp, comp);
+ if (diff) {
+ const unsigned char *prev = begin;
+ for (k = i + 2; k < x && len < 128; ++k) {
+ if (memcmp(prev, row + k * comp, comp)) {
+ prev += comp;
+ ++len;
+ } else {
+ --len;
+ break;
+ }
+ }
+ } else {
+ for (k = i + 2; k < x && len < 128; ++k) {
+ if (!memcmp(begin, row + k * comp, comp)) {
+ ++len;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ if (diff) {
+ unsigned char header = STBIW_UCHAR(len - 1);
+ s->func(s->context, &header, 1);
+ for (k = 0; k < len; ++k) {
+ stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
+ }
+ } else {
+ unsigned char header = STBIW_UCHAR(len - 129);
+ s->func(s->context, &header, 1);
+ stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
+{
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_tga_core(&s, x, y, comp, (void *) data);
}
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
+{
+ stbi__write_context s;
+ if (stbi__start_write_file(&s,filename)) {
+ int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
+}
+#endif
+
// *************************************************************************************************
// Radiance RGBE HDR writer
// by Baldur Karlsson
+
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
@@ -217,7 +497,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
int exponent;
float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
- if (maxcomp < 1e-32) {
+ if (maxcomp < 1e-32f) {
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
} else {
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
@@ -229,23 +509,23 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
}
}
-void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
+void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
{
- unsigned char lengthbyte = (unsigned char) (length+128);
- assert(length+128 <= 255);
- fwrite(&lengthbyte, 1, 1, f);
- fwrite(&databyte, 1, 1, f);
+ unsigned char lengthbyte = STBIW_UCHAR(length+128);
+ STBIW_ASSERT(length+128 <= 255);
+ s->func(s->context, &lengthbyte, 1);
+ s->func(s->context, &databyte, 1);
}
-void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
+void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
{
- unsigned char lengthbyte = (unsigned char )(length & 0xff);
- assert(length <= 128); // inconsistent with spec but consistent with official code
- fwrite(&lengthbyte, 1, 1, f);
- fwrite(data, length, 1, f);
+ unsigned char lengthbyte = STBIW_UCHAR(length);
+ STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
+ s->func(s->context, &lengthbyte, 1);
+ s->func(s->context, data, length);
}
-void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
+void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
{
unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
unsigned char rgbe[4];
@@ -258,31 +538,31 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
/* skip RLE for images too small or large */
if (width < 8 || width >= 32768) {
for (x=0; x < width; x++) {
- switch (comp) {
+ switch (ncomp) {
case 4: /* fallthrough */
- case 3: linear[2] = scanline[x*comp + 2];
- linear[1] = scanline[x*comp + 1];
- linear[0] = scanline[x*comp + 0];
+ case 3: linear[2] = scanline[x*ncomp + 2];
+ linear[1] = scanline[x*ncomp + 1];
+ linear[0] = scanline[x*ncomp + 0];
break;
- case 2: /* fallthrough */
- case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
+ default:
+ linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
break;
}
stbiw__linear_to_rgbe(rgbe, linear);
- fwrite(rgbe, 4, 1, f);
+ s->func(s->context, rgbe, 4);
}
} else {
int c,r;
/* encode into scratch buffer */
for (x=0; x < width; x++) {
- switch(comp) {
+ switch(ncomp) {
case 4: /* fallthrough */
- case 3: linear[2] = scanline[x*comp + 2];
- linear[1] = scanline[x*comp + 1];
- linear[0] = scanline[x*comp + 0];
+ case 3: linear[2] = scanline[x*ncomp + 2];
+ linear[1] = scanline[x*ncomp + 1];
+ linear[0] = scanline[x*ncomp + 0];
break;
- case 2: /* fallthrough */
- case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
+ default:
+ linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
break;
}
stbiw__linear_to_rgbe(rgbe, linear);
@@ -292,12 +572,11 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
scratch[x + width*3] = rgbe[3];
}
- fwrite(scanlineheader, 4, 1, f);
+ s->func(s->context, scanlineheader, 4);
/* RLE each component separately */
for (c=0; c < 4; c++) {
unsigned char *comp = &scratch[width*c];
- int runstart = 0, head = 0, rlerun = 0;
x = 0;
while (x < width) {
@@ -314,19 +593,19 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
while (x < r) {
int len = r-x;
if (len > 128) len = 128;
- stbiw__write_dump_data(f, len, &comp[x]);
+ stbiw__write_dump_data(s, len, &comp[x]);
x += len;
}
// if there's a run, output it
if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
// find next byte after run
while (r < width && comp[r] == comp[x])
- ++r;
+ ++r;
// output run up to r
while (x < r) {
int len = r-x;
if (len > 127) len = 127;
- stbiw__write_run_data(f, len, comp[x]);
+ stbiw__write_run_data(s, len, comp[x]);
x += len;
}
}
@@ -335,27 +614,53 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
}
}
-int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
+static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
{
- int i;
- FILE *f;
- if (y <= 0 || x <= 0 || data == NULL) return 0;
- f = fopen(filename, "wb");
- if (f) {
- /* Each component is stored separately. Allocate scratch space for full output scanline. */
- unsigned char *scratch = (unsigned char *) malloc(x*4);
- fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" );
- fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
+ if (y <= 0 || x <= 0 || data == NULL)
+ return 0;
+ else {
+ // Each component is stored separately. Allocate scratch space for full output scanline.
+ unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
+ int i, len;
+ char buffer[128];
+ char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
+ s->func(s->context, header, sizeof(header)-1);
+
+ len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
+ s->func(s->context, buffer, len);
+
for(i=0; i < y; i++)
- stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
- free(scratch);
- fclose(f);
+ stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
+ STBIW_FREE(scratch);
+ return 1;
}
- return f != NULL;
}
-/////////////////////////////////////////////////////////
-// PNG
+STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
+{
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
+}
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
+{
+ stbi__write_context s;
+ if (stbi__start_write_file(&s,filename)) {
+ int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
+}
+#endif // STBI_WRITE_NO_STDIO
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PNG writer
+//
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2)
@@ -368,13 +673,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da
#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
-#define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0)
+#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
{
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
- void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
- assert(p);
+ void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
+ STBIW_ASSERT(p);
if (p) {
if (!*arr) ((int *) p)[1] = 0;
*arr = (void *) ((int *) p + 2);
@@ -386,7 +691,7 @@ static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
{
while (*bitcount >= 8) {
- stbiw__sbpush(data, (unsigned char) *bitbuffer);
+ stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
*bitbuffer >>= 8;
*bitcount -= 8;
}
@@ -446,7 +751,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
unsigned int bitbuf=0;
int i,j, bitcount=0;
unsigned char *out = NULL;
- unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
+ unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
if (quality < 5) quality = 5;
stbiw__sbpush(out, 0x78); // DEFLATE 32K window
@@ -459,7 +764,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
i=0;
while (i < data_len-3) {
- // hash next 3 bytes of data to be compressed
+ // hash next 3 bytes of data to be compressed
int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
unsigned char *bestloc = 0;
unsigned char **hlist = hash_table[h];
@@ -472,7 +777,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
}
// when hash table entry is too long, delete half the entries
if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
- memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
+ STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
stbiw__sbn(hash_table[h]) = quality;
}
stbiw__sbpush(hash_table[h],data+i);
@@ -495,7 +800,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
if (bestloc) {
int d = (int) (data+i - bestloc); // distance back
- assert(d <= 32767 && best <= 258);
+ STBIW_ASSERT(d <= 32767 && best <= 258);
for (j=0; best > lengthc[j+1]-1; ++j);
stbiw__zlib_huff(j+257);
if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
@@ -518,43 +823,76 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
for (i=0; i < stbiw__ZHASH; ++i)
(void) stbiw__sbfree(hash_table[i]);
+ STBIW_FREE(hash_table);
{
// compute adler32 on input
- unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
- int j=0;
+ unsigned int s1=1, s2=0;
+ int blocklen = (int) (data_len % 5552);
+ j=0;
while (j < data_len) {
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
s1 %= 65521, s2 %= 65521;
j += blocklen;
blocklen = 5552;
}
- stbiw__sbpush(out, (unsigned char) (s2 >> 8));
- stbiw__sbpush(out, (unsigned char) s2);
- stbiw__sbpush(out, (unsigned char) (s1 >> 8));
- stbiw__sbpush(out, (unsigned char) s1);
+ stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
+ stbiw__sbpush(out, STBIW_UCHAR(s2));
+ stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
+ stbiw__sbpush(out, STBIW_UCHAR(s1));
}
*out_len = stbiw__sbn(out);
// make returned pointer freeable
- memmove(stbiw__sbraw(out), out, *out_len);
+ STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
return (unsigned char *) stbiw__sbraw(out);
}
-unsigned int stbiw__crc32(unsigned char *buffer, int len)
+static unsigned int stbiw__crc32(unsigned char *buffer, int len)
{
- static unsigned int crc_table[256];
+ static unsigned int crc_table[256] =
+ {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+ };
+
unsigned int crc = ~0u;
- int i,j;
- if (crc_table[1] == 0)
- for(i=0; i < 256; i++)
- for (crc_table[i]=i, j=0; j < 8; ++j)
- crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
+ int i;
for (i=0; i < len; ++i)
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
return ~crc;
}
-#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
+#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
@@ -567,11 +905,12 @@ static void stbiw__wpcrc(unsigned char **data, int len)
static unsigned char stbiw__paeth(int a, int b, int c)
{
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
- if (pa <= pb && pa <= pc) return (unsigned char) a;
- if (pb <= pc) return (unsigned char) b;
- return (unsigned char) c;
+ if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
+ if (pb <= pc) return STBIW_UCHAR(b);
+ return STBIW_UCHAR(c);
}
+// @OPTIMIZE: provide an option that always forces left-predict or paeth predict
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
{
int ctype[5] = { -1, 0, 4, 2, 6 };
@@ -583,15 +922,15 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
if (stride_bytes == 0)
stride_bytes = x * n;
- filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
- line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
+ filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
+ line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
for (j=0; j < y; ++j) {
static int mapping[] = { 0,1,2,3,4 };
static int firstmap[] = { 0,1,0,5,6 };
- int *mymap = j ? mapping : firstmap;
+ int *mymap = (j != 0) ? mapping : firstmap;
int best = 0, bestval = 0x7fffffff;
for (p=0; p < 2; ++p) {
- for (k= p?best:0; k < 5; ++k) {
+ for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass
int type = mymap[k],est=0;
unsigned char *z = pixels + stride_bytes*j;
for (i=0; i < n; ++i)
@@ -623,26 +962,26 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
}
// when we get here, best contains the filter type, and line_buffer contains the data
filt[j*(x*n+1)] = (unsigned char) best;
- memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
+ STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
}
- free(line_buffer);
+ STBIW_FREE(line_buffer);
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
- free(filt);
+ STBIW_FREE(filt);
if (!zlib) return 0;
// each tag requires 12 bytes of overhead
- out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
+ out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
if (!out) return 0;
*out_len = 8 + 12+13 + 12+zlen + 12;
o=out;
- memcpy(o,sig,8); o+= 8;
+ STBIW_MEMMOVE(o,sig,8); o+= 8;
stbiw__wp32(o, 13); // header length
stbiw__wptag(o, "IHDR");
stbiw__wp32(o, x);
stbiw__wp32(o, y);
*o++ = 8;
- *o++ = (unsigned char) ctype[n];
+ *o++ = STBIW_UCHAR(ctype[n]);
*o++ = 0;
*o++ = 0;
*o++ = 0;
@@ -650,35 +989,414 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
stbiw__wp32(o, zlen);
stbiw__wptag(o, "IDAT");
- memcpy(o, zlib, zlen); o += zlen; free(zlib);
+ STBIW_MEMMOVE(o, zlib, zlen);
+ o += zlen;
+ STBIW_FREE(zlib);
stbiw__wpcrc(&o, zlen);
stbiw__wp32(o,0);
stbiw__wptag(o, "IEND");
stbiw__wpcrc(&o,0);
- assert(o == out + *out_len);
+ STBIW_ASSERT(o == out + *out_len);
return out;
}
-int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
{
FILE *f;
int len;
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
- if (!png) return 0;
+ if (png == NULL) return 0;
f = fopen(filename, "wb");
- if (!f) { free(png); return 0; }
+ if (!f) { STBIW_FREE(png); return 0; }
fwrite(png, 1, len, f);
fclose(f);
- free(png);
+ STBIW_FREE(png);
+ return 1;
+}
+#endif
+
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
+{
+ int len;
+ unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
+ if (png == NULL) return 0;
+ func(context, png, len);
+ STBIW_FREE(png);
+ return 1;
+}
+
+
+/* ***************************************************************************
+ *
+ * JPEG writer
+ *
+ * This is based on Jon Olick's jo_jpeg.cpp:
+ * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
+ */
+
+static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
+ 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
+
+static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
+ int bitBuf = *bitBufP, bitCnt = *bitCntP;
+ bitCnt += bs[1];
+ bitBuf |= bs[0] << (24 - bitCnt);
+ while(bitCnt >= 8) {
+ unsigned char c = (bitBuf >> 16) & 255;
+ stbiw__putc(s, c);
+ if(c == 255) {
+ stbiw__putc(s, 0);
+ }
+ bitBuf <<= 8;
+ bitCnt -= 8;
+ }
+ *bitBufP = bitBuf;
+ *bitCntP = bitCnt;
+}
+
+static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
+ float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
+ float z1, z2, z3, z4, z5, z11, z13;
+
+ float tmp0 = d0 + d7;
+ float tmp7 = d0 - d7;
+ float tmp1 = d1 + d6;
+ float tmp6 = d1 - d6;
+ float tmp2 = d2 + d5;
+ float tmp5 = d2 - d5;
+ float tmp3 = d3 + d4;
+ float tmp4 = d3 - d4;
+
+ // Even part
+ float tmp10 = tmp0 + tmp3; // phase 2
+ float tmp13 = tmp0 - tmp3;
+ float tmp11 = tmp1 + tmp2;
+ float tmp12 = tmp1 - tmp2;
+
+ d0 = tmp10 + tmp11; // phase 3
+ d4 = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * 0.707106781f; // c4
+ d2 = tmp13 + z1; // phase 5
+ d6 = tmp13 - z1;
+
+ // Odd part
+ tmp10 = tmp4 + tmp5; // phase 2
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ // The rotator is modified from fig 4-8 to avoid extra negations.
+ z5 = (tmp10 - tmp12) * 0.382683433f; // c6
+ z2 = tmp10 * 0.541196100f + z5; // c2-c6
+ z4 = tmp12 * 1.306562965f + z5; // c2+c6
+ z3 = tmp11 * 0.707106781f; // c4
+
+ z11 = tmp7 + z3; // phase 5
+ z13 = tmp7 - z3;
+
+ *d5p = z13 + z2; // phase 6
+ *d3p = z13 - z2;
+ *d1p = z11 + z4;
+ *d7p = z11 - z4;
+
+ *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
+}
+
+static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
+ int tmp1 = val < 0 ? -val : val;
+ val = val < 0 ? val-1 : val;
+ bits[1] = 1;
+ while(tmp1 >>= 1) {
+ ++bits[1];
+ }
+ bits[0] = val & ((1<<bits[1])-1);
+}
+
+static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
+ const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
+ const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
+ int dataOff, i, diff, end0pos;
+ int DU[64];
+
+ // DCT rows
+ for(dataOff=0; dataOff<64; dataOff+=8) {
+ stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
+ }
+ // DCT columns
+ for(dataOff=0; dataOff<8; ++dataOff) {
+ stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
+ }
+ // Quantize/descale/zigzag the coefficients
+ for(i=0; i<64; ++i) {
+ float v = CDU[i]*fdtbl[i];
+ // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
+ // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
+ DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
+ }
+
+ // Encode DC
+ diff = DU[0] - DC;
+ if (diff == 0) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
+ } else {
+ unsigned short bits[2];
+ stbiw__jpg_calcBits(diff, bits);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+ }
+ // Encode ACs
+ end0pos = 63;
+ for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
+ }
+ // end0pos = first element in reverse order !=0
+ if(end0pos == 0) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+ return DU[0];
+ }
+ for(i = 1; i <= end0pos; ++i) {
+ int startpos = i;
+ int nrzeroes;
+ unsigned short bits[2];
+ for (; DU[i]==0 && i<=end0pos; ++i) {
+ }
+ nrzeroes = i-startpos;
+ if ( nrzeroes >= 16 ) {
+ int lng = nrzeroes>>4;
+ int nrmarker;
+ for (nrmarker=1; nrmarker <= lng; ++nrmarker)
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
+ nrzeroes &= 15;
+ }
+ stbiw__jpg_calcBits(DU[i], bits);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+ }
+ if(end0pos != 63) {
+ stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+ }
+ return DU[0];
+}
+
+static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
+ // Constants that don't pollute global namespace
+ static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
+ static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
+ static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
+ static const unsigned char std_ac_luminance_values[] = {
+ 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
+ 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
+ 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
+ 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
+ 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
+ 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
+ 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
+ };
+ static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
+ static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
+ static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
+ static const unsigned char std_ac_chrominance_values[] = {
+ 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
+ 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
+ 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
+ 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
+ 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
+ 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
+ };
+ // Huffman tables
+ static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
+ static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
+ static const unsigned short YAC_HT[256][2] = {
+ {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
+ };
+ static const unsigned short UVAC_HT[256][2] = {
+ {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
+ {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
+ };
+ static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
+ 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
+ static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
+ 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
+ static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
+ 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
+
+ int row, col, i, k;
+ float fdtbl_Y[64], fdtbl_UV[64];
+ unsigned char YTable[64], UVTable[64];
+
+ if(!data || !width || !height || comp > 4 || comp < 1) {
+ return 0;
+ }
+
+ quality = quality ? quality : 90;
+ quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
+ quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
+
+ for(i = 0; i < 64; ++i) {
+ int uvti, yti = (YQT[i]*quality+50)/100;
+ YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
+ uvti = (UVQT[i]*quality+50)/100;
+ UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
+ }
+
+ for(row = 0, k = 0; row < 8; ++row) {
+ for(col = 0; col < 8; ++col, ++k) {
+ fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+ fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+ }
+ }
+
+ // Write Headers
+ {
+ static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
+ static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
+ const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
+ 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
+ s->func(s->context, (void*)head0, sizeof(head0));
+ s->func(s->context, (void*)YTable, sizeof(YTable));
+ stbiw__putc(s, 1);
+ s->func(s->context, UVTable, sizeof(UVTable));
+ s->func(s->context, (void*)head1, sizeof(head1));
+ s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
+ s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
+ stbiw__putc(s, 0x10); // HTYACinfo
+ s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
+ s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
+ stbiw__putc(s, 1); // HTUDCinfo
+ s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
+ s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
+ stbiw__putc(s, 0x11); // HTUACinfo
+ s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
+ s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
+ s->func(s->context, (void*)head2, sizeof(head2));
+ }
+
+ // Encode 8x8 macroblocks
+ {
+ static const unsigned short fillBits[] = {0x7F, 7};
+ const unsigned char *imageData = (const unsigned char *)data;
+ int DCY=0, DCU=0, DCV=0;
+ int bitBuf=0, bitCnt=0;
+ // comp == 2 is grey+alpha (alpha is ignored)
+ int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
+ int x, y, pos;
+ for(y = 0; y < height; y += 8) {
+ for(x = 0; x < width; x += 8) {
+ float YDU[64], UDU[64], VDU[64];
+ for(row = y, pos = 0; row < y+8; ++row) {
+ for(col = x; col < x+8; ++col, ++pos) {
+ int p = row*width*comp + col*comp;
+ float r, g, b;
+ if(row >= height) {
+ p -= width*comp*(row+1 - height);
+ }
+ if(col >= width) {
+ p -= comp*(col+1 - width);
+ }
+
+ r = imageData[p+0];
+ g = imageData[p+ofsG];
+ b = imageData[p+ofsB];
+ YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
+ UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
+ VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
+ }
+ }
+
+ DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+ DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+ DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
+ }
+ }
+
+ // Do the bit alignment of the EOI marker
+ stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
+ }
+
+ // EOI
+ stbiw__putc(s, 0xFF);
+ stbiw__putc(s, 0xD9);
+
return 1;
}
+
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
+{
+ stbi__write_context s;
+ stbi__start_write_callbacks(&s, func, context);
+ return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
+}
+
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
+{
+ stbi__write_context s;
+ if (stbi__start_write_file(&s,filename)) {
+ int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
+ stbi__end_write_file(&s);
+ return r;
+ } else
+ return 0;
+}
+#endif
+
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history
-
+ 1.07 (2017-07-24)
+ doc fix
+ 1.06 (2017-07-23)
+ writing JPEG (using Jon Olick's code)
+ 1.05 ???
+ 1.04 (2017-03-03)
+ monochrome BMP expansion
+ 1.03 ???
+ 1.02 (2016-04-02)
+ avoid allocating large structures on the stack
+ 1.01 (2016-01-16)
+ STBIW_REALLOC_SIZED: support allocators with no realloc support
+ avoid race-condition in crc initialization
+ minor compile issues
+ 1.00 (2015-09-14)
+ installable file IO function
+ 0.99 (2015-09-13)
+ warning fixes; TGA rle support
+ 0.98 (2015-04-08)
+ added STBIW_MALLOC, STBIW_ASSERT etc
0.97 (2015-01-18)
fixed HDR asserts, rewrote HDR rle logic
0.96 (2015-01-17)
@@ -696,3 +1414,45 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat
first public release
0.90 first internal release
*/
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/include/SFML/Audio.hpp b/include/SFML/Audio.hpp
index 2d3e5d7..3167927 100644
--- a/include/SFML/Audio.hpp
+++ b/include/SFML/Audio.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/AlResource.hpp b/include/SFML/Audio/AlResource.hpp
index 2cb48d0..dd7d44c 100644
--- a/include/SFML/Audio/AlResource.hpp
+++ b/include/SFML/Audio/AlResource.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/Export.hpp b/include/SFML/Audio/Export.hpp
index 31e463e..9e5e09c 100644
--- a/include/SFML/Audio/Export.hpp
+++ b/include/SFML/Audio/Export.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/InputSoundFile.hpp b/include/SFML/Audio/InputSoundFile.hpp
index 672ea43..317b952 100644
--- a/include/SFML/Audio/InputSoundFile.hpp
+++ b/include/SFML/Audio/InputSoundFile.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -32,6 +32,7 @@
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Time.hpp>
#include <string>
+#include <algorithm>
namespace sf
@@ -100,18 +101,6 @@ public:
bool openFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
- /// \brief Open the sound file from the disk for writing
- ///
- /// \param filename Path of the sound file to write
- /// \param channelCount Number of channels in the sound
- /// \param sampleRate Sample rate of the sound
- ///
- /// \return True if the file was successfully opened
- ///
- ////////////////////////////////////////////////////////////
- bool openForWriting(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
-
- ////////////////////////////////////////////////////////////
/// \brief Get the total number of audio samples in the file
///
/// \return Number of samples
@@ -147,6 +136,22 @@ public:
Time getDuration() const;
////////////////////////////////////////////////////////////
+ /// \brief Get the read offset of the file in time
+ ///
+ /// \return Time position
+ ///
+ ////////////////////////////////////////////////////////////
+ Time getTimeOffset() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the read offset of the file in samples
+ ///
+ /// \return Sample position
+ ///
+ ////////////////////////////////////////////////////////////
+ Uint64 getSampleOffset() const;
+
+ ////////////////////////////////////////////////////////////
/// \brief Change the current read position to the given sample offset
///
/// This function takes a sample offset to provide maximum
@@ -154,8 +159,9 @@ public:
/// other overload.
///
/// The sample offset takes the channels into account.
- /// Offsets can be calculated like this:
- /// `sampleNumber * sampleRate * channelCount`
+ /// If you have a time offset instead, you can easily find
+ /// the corresponding sample offset with the following formula:
+ /// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function jumps to the end of the sound file.
///
@@ -203,6 +209,7 @@ private:
SoundFileReader* m_reader; ///< Reader that handles I/O on the file's format
InputStream* m_stream; ///< Input stream used to access the file's data
bool m_streamOwned; ///< Is the stream internal or external?
+ Uint64 m_sampleOffset; ///< Sample Read Position
Uint64 m_sampleCount; ///< Total number of samples in the file
unsigned int m_channelCount; ///< Number of channels of the sound
unsigned int m_sampleRate; ///< Number of samples per second
diff --git a/include/SFML/Audio/Listener.hpp b/include/SFML/Audio/Listener.hpp
index af83e25..9fb7fff 100644
--- a/include/SFML/Audio/Listener.hpp
+++ b/include/SFML/Audio/Listener.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp
index 8114923..5351905 100644
--- a/include/SFML/Audio/Music.hpp
+++ b/include/SFML/Audio/Music.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -50,6 +50,43 @@ class SFML_AUDIO_API Music : public SoundStream
public:
////////////////////////////////////////////////////////////
+ /// \brief Structure defining a time range using the template type
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ struct Span
+ {
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ ////////////////////////////////////////////////////////////
+ Span()
+ {
+
+ }
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Initialization constructor
+ ///
+ /// \param off Initial Offset
+ /// \param len Initial Length
+ ///
+ ////////////////////////////////////////////////////////////
+ Span(T off, T len):
+ offset(off),
+ length(len)
+ {
+
+ }
+
+ T offset; ///< The beginning offset of the time range
+ T length; ///< The length of the time range
+ };
+
+ // Define the relevant Span types
+ typedef Span<Time> TimeSpan;
+
+ ////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
@@ -134,6 +171,45 @@ public:
////////////////////////////////////////////////////////////
Time getDuration() const;
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the positions of the of the sound's looping sequence
+ ///
+ /// \return Loop Time position class.
+ ///
+ /// \warning Since setLoopPoints() performs some adjustments on the
+ /// provided values and rounds them to internal samples, a call to
+ /// getLoopPoints() is not guaranteed to return the same times passed
+ /// into a previous call to setLoopPoints(). However, it is guaranteed
+ /// to return times that will map to the valid internal samples of
+ /// this Music if they are later passed to setLoopPoints().
+ ///
+ /// \see setLoopPoints
+ ///
+ ////////////////////////////////////////////////////////////
+ TimeSpan getLoopPoints() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Sets the beginning and end of the sound's looping sequence using sf::Time
+ ///
+ /// Loop points allow one to specify a pair of positions such that, when the music
+ /// is enabled for looping, it will seamlessly seek to the beginning whenever it
+ /// encounters the end. Valid ranges for timePoints.offset and timePoints.length are
+ /// [0, Dur) and (0, Dur-offset] respectively, where Dur is the value returned by getDuration().
+ /// Note that the EOF "loop point" from the end to the beginning of the stream is still honored,
+ /// in case the caller seeks to a point after the end of the loop range. This function can be
+ /// safely called at any point after a stream is opened, and will be applied to a playing sound
+ /// without affecting the current playing offset.
+ ///
+ /// \warning Setting the loop points while the stream's status is Paused
+ /// will set its status to Stopped. The playing offset will be unaffected.
+ ///
+ /// \param timePoints The definition of the loop. Can be any time points within the sound's length
+ ///
+ /// \see getLoopPoints
+ ///
+ ////////////////////////////////////////////////////////////
+ void setLoopPoints(TimeSpan timePoints);
+
protected:
////////////////////////////////////////////////////////////
@@ -157,6 +233,18 @@ protected:
////////////////////////////////////////////////////////////
virtual void onSeek(Time timeOffset);
+ ////////////////////////////////////////////////////////////
+ /// \brief Change the current playing position in the stream source to the loop offset
+ ///
+ /// This is called by the underlying SoundStream whenever it needs us to reset
+ /// the seek position for a loop. We then determine whether we are looping on a
+ /// loop point or the end-of-file, perform the seek, and return the new position.
+ ///
+ /// \return The seek position after looping (or -1 if there's no loop)
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual Int64 onLoop();
+
private:
////////////////////////////////////////////////////////////
@@ -166,12 +254,32 @@ private:
void initialize();
////////////////////////////////////////////////////////////
+ /// \brief Helper to convert an sf::Time to a sample position
+ ///
+ /// \param position Time to convert to samples
+ ///
+ /// \return The number of samples elapsed at the given time
+ ///
+ ////////////////////////////////////////////////////////////
+ Uint64 timeToSamples(Time position) const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Helper to convert a sample position to an sf::Time
+ ///
+ /// \param samples Sample count to convert to Time
+ ///
+ /// \return The Time position of the given sample
+ ///
+ ////////////////////////////////////////////////////////////
+ Time samplesToTime(Uint64 samples) const;
+
+ ////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
InputSoundFile m_file; ///< The streamed music file
- Time m_duration; ///< Music duration
std::vector<Int16> m_samples; ///< Temporary buffer of samples
Mutex m_mutex; ///< Mutex protecting the data
+ Span<Uint64> m_loopSpan; ///< Loop Range Specifier
};
} // namespace sf
diff --git a/include/SFML/Audio/OutputSoundFile.hpp b/include/SFML/Audio/OutputSoundFile.hpp
index 325b38f..5da374b 100644
--- a/include/SFML/Audio/OutputSoundFile.hpp
+++ b/include/SFML/Audio/OutputSoundFile.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/Sound.hpp b/include/SFML/Audio/Sound.hpp
index 3b20024..f8e2e14 100644
--- a/include/SFML/Audio/Sound.hpp
+++ b/include/SFML/Audio/Sound.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundBuffer.hpp b/include/SFML/Audio/SoundBuffer.hpp
index 6303cfb..5aaa4ca 100644
--- a/include/SFML/Audio/SoundBuffer.hpp
+++ b/include/SFML/Audio/SoundBuffer.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundBufferRecorder.hpp b/include/SFML/Audio/SoundBufferRecorder.hpp
index b5b6436..266603d 100644
--- a/include/SFML/Audio/SoundBufferRecorder.hpp
+++ b/include/SFML/Audio/SoundBufferRecorder.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundFileFactory.hpp b/include/SFML/Audio/SoundFileFactory.hpp
index b4eadf0..e3719c8 100644
--- a/include/SFML/Audio/SoundFileFactory.hpp
+++ b/include/SFML/Audio/SoundFileFactory.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundFileFactory.inl b/include/SFML/Audio/SoundFileFactory.inl
index a552ba8..6c499f3 100644
--- a/include/SFML/Audio/SoundFileFactory.inl
+++ b/include/SFML/Audio/SoundFileFactory.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundFileReader.hpp b/include/SFML/Audio/SoundFileReader.hpp
index 006ce65..a040db9 100644
--- a/include/SFML/Audio/SoundFileReader.hpp
+++ b/include/SFML/Audio/SoundFileReader.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -80,8 +80,9 @@ public:
/// \brief Change the current read position to the given sample offset
///
/// The sample offset takes the channels into account.
- /// Offsets can be calculated like this:
- /// `sampleNumber * sampleRate * channelCount`
+ /// If you have a time offset instead, you can easily find
+ /// the corresponding sample offset with the following formula:
+ /// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
diff --git a/include/SFML/Audio/SoundFileWriter.hpp b/include/SFML/Audio/SoundFileWriter.hpp
index 8a35a0d..8651ddc 100644
--- a/include/SFML/Audio/SoundFileWriter.hpp
+++ b/include/SFML/Audio/SoundFileWriter.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundRecorder.hpp b/include/SFML/Audio/SoundRecorder.hpp
index 33c80b1..d4dc74f 100644
--- a/include/SFML/Audio/SoundRecorder.hpp
+++ b/include/SFML/Audio/SoundRecorder.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Audio/SoundSource.hpp b/include/SFML/Audio/SoundSource.hpp
index edcaaa2..fcc9c79 100644
--- a/include/SFML/Audio/SoundSource.hpp
+++ b/include/SFML/Audio/SoundSource.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -250,15 +250,40 @@ public:
////////////////////////////////////////////////////////////
SoundSource& operator =(const SoundSource& right);
-protected:
+ ////////////////////////////////////////////////////////////
+ /// \brief Start or resume playing the sound source
+ ///
+ /// This function starts the source if it was stopped, resumes
+ /// it if it was paused, and restarts it from the beginning if
+ /// it was already playing.
+ ///
+ /// \see pause, stop
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void play() = 0;
////////////////////////////////////////////////////////////
- /// \brief Default constructor
+ /// \brief Pause the sound source
///
- /// This constructor is meant to be called by derived classes only.
+ /// This function pauses the source if it was playing,
+ /// otherwise (source already paused or stopped) it has no effect.
+ ///
+ /// \see play, stop
///
////////////////////////////////////////////////////////////
- SoundSource();
+ virtual void pause() = 0;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Stop playing the sound source
+ ///
+ /// This function stops the source if it was playing or paused,
+ /// and does nothing if it was already stopped.
+ /// It also resets the playing position (unlike pause()).
+ ///
+ /// \see play, pause
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void stop() = 0;
////////////////////////////////////////////////////////////
/// \brief Get the current status of the sound (stopped, paused, playing)
@@ -266,7 +291,17 @@ protected:
/// \return Current status of the sound
///
////////////////////////////////////////////////////////////
- Status getStatus() const;
+ virtual Status getStatus() const;
+
+protected:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// This constructor is meant to be called by derived classes only.
+ ///
+ ////////////////////////////////////////////////////////////
+ SoundSource();
////////////////////////////////////////////////////////////
// Member data
diff --git a/include/SFML/Audio/SoundStream.hpp b/include/SFML/Audio/SoundStream.hpp
index 06856ed..bed8311 100644
--- a/include/SFML/Audio/SoundStream.hpp
+++ b/include/SFML/Audio/SoundStream.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -180,6 +180,11 @@ public:
protected:
+ enum
+ {
+ NoLoop = -1 ///< "Invalid" endSeeks value, telling us to continue uninterrupted
+ };
+
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
@@ -234,6 +239,18 @@ protected:
////////////////////////////////////////////////////////////
virtual void onSeek(Time timeOffset) = 0;
+ ////////////////////////////////////////////////////////////
+ /// \brief Change the current playing position in the stream source to the beginning of the loop
+ ///
+ /// This function can be overridden by derived classes to
+ /// allow implementation of custom loop points. Otherwise,
+ /// it just calls onSeek(Time::Zero) and returns 0.
+ ///
+ /// \return The seek position after looping (or -1 if there's no loop)
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual Int64 onLoop();
+
private:
////////////////////////////////////////////////////////////
@@ -254,11 +271,12 @@ private:
/// playing queue.
///
/// \param bufferNum Number of the buffer to fill (in [0, BufferCount])
+ /// \param immediateLoop Treat empty buffers as spent, and act on loops immediately
///
/// \return True if the stream source has requested to stop, false otherwise
///
////////////////////////////////////////////////////////////
- bool fillAndPushBuffer(unsigned int bufferNum);
+ bool fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop = false);
////////////////////////////////////////////////////////////
/// \brief Fill the audio buffers and put them all into the playing queue
@@ -281,23 +299,24 @@ private:
enum
{
- BufferCount = 3 ///< Number of audio buffers used by the streaming loop
+ BufferCount = 3, ///< Number of audio buffers used by the streaming loop
+ BufferRetries = 2 ///< Number of retries (excluding initial try) for onGetData()
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- Thread m_thread; ///< Thread running the background tasks
- mutable Mutex m_threadMutex; ///< Thread mutex
- Status m_threadStartState; ///< State the thread starts in (Playing, Paused, Stopped)
- bool m_isStreaming; ///< Streaming state (true = playing, false = stopped)
- unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data
- unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...)
- unsigned int m_sampleRate; ///< Frequency (samples / second)
- Uint32 m_format; ///< Format of the internal sound buffers
- bool m_loop; ///< Loop flag (true to loop, false to play once)
- Uint64 m_samplesProcessed; ///< Number of buffers processed since beginning of the stream
- bool m_endBuffers[BufferCount]; ///< Each buffer is marked as "end buffer" or not, for proper duration calculation
+ Thread m_thread; ///< Thread running the background tasks
+ mutable Mutex m_threadMutex; ///< Thread mutex
+ Status m_threadStartState; ///< State the thread starts in (Playing, Paused, Stopped)
+ bool m_isStreaming; ///< Streaming state (true = playing, false = stopped)
+ unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data
+ unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...)
+ unsigned int m_sampleRate; ///< Frequency (samples / second)
+ Uint32 m_format; ///< Format of the internal sound buffers
+ bool m_loop; ///< Loop flag (true to loop, false to play once)
+ Uint64 m_samplesProcessed; ///< Number of buffers processed since beginning of the stream
+ Int64 m_bufferSeeks[BufferCount]; ///< If buffer is an "end buffer", holds next seek position, else NoLoop. For play offset calculation.
};
} // namespace sf
diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp
index 5a8a87c..aae5f54 100644
--- a/include/SFML/Config.hpp
+++ b/include/SFML/Config.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -30,8 +30,8 @@
// Define the SFML version
////////////////////////////////////////////////////////////
#define SFML_VERSION_MAJOR 2
-#define SFML_VERSION_MINOR 4
-#define SFML_VERSION_PATCH 2
+#define SFML_VERSION_MINOR 5
+#define SFML_VERSION_PATCH 0
////////////////////////////////////////////////////////////
@@ -86,6 +86,11 @@
// FreeBSD
#define SFML_SYSTEM_FREEBSD
+ #elif defined(__OpenBSD__)
+
+ // OpenBSD
+ #define SFML_SYSTEM_OPENBSD
+
#else
// Unsupported UNIX system
diff --git a/include/SFML/GpuPreference.hpp b/include/SFML/GpuPreference.hpp
new file mode 100644
index 0000000..cde4f9f
--- /dev/null
+++ b/include/SFML/GpuPreference.hpp
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_GPUPREFERENCE_HPP
+#define SFML_GPUPREFERENCE_HPP
+
+
+////////////////////////////////////////////////////////////
+/// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+
+
+////////////////////////////////////////////////////////////
+/// \file
+///
+/// \brief File containing SFML_DEFINE_DISCRETE_GPU_PREFERENCE
+///
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+/// \def SFML_DEFINE_DISCRETE_GPU_PREFERENCE
+///
+/// \brief A macro to encourage usage of the discrete GPU
+///
+/// In order to inform the Nvidia/AMD driver that an SFML
+/// application could benefit from using the more powerful
+/// discrete GPU, special symbols have to be publicly
+/// exported from the final executable.
+///
+/// SFML defines a helper macro to easily do this.
+///
+/// Place SFML_DEFINE_DISCRETE_GPU_PREFERENCE in the
+/// global scope of a source file that will be linked into
+/// the final executable. Typically it is best to place it
+/// where the main function is also defined.
+///
+////////////////////////////////////////////////////////////
+#if defined(SFML_SYSTEM_WINDOWS)
+
+ #define SFML_DEFINE_DISCRETE_GPU_PREFERENCE \
+ extern "C" __declspec(dllexport) unsigned long NvOptimusEnablement = 1; \
+ extern "C" __declspec(dllexport) unsigned long AmdPowerXpressRequestHighPerformance = 1;
+
+#else
+
+ #define SFML_DEFINE_DISCRETE_GPU_PREFERENCE
+
+#endif
+
+
+#endif // SFML_GPUPREFERENCE_HPP
diff --git a/include/SFML/Graphics.hpp b/include/SFML/Graphics.hpp
index 5bb622a..252c6e9 100644
--- a/include/SFML/Graphics.hpp
+++ b/include/SFML/Graphics.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -54,6 +54,7 @@
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/VertexArray.hpp>
+#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/View.hpp>
diff --git a/include/SFML/Graphics/BlendMode.hpp b/include/SFML/Graphics/BlendMode.hpp
index 3ba0a40..15da7d1 100644
--- a/include/SFML/Graphics/BlendMode.hpp
+++ b/include/SFML/Graphics/BlendMode.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/CircleShape.hpp b/include/SFML/Graphics/CircleShape.hpp
index 9f68969..896c893 100644
--- a/include/SFML/Graphics/CircleShape.hpp
+++ b/include/SFML/Graphics/CircleShape.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Color.hpp b/include/SFML/Graphics/Color.hpp
index 1f81feb..43357aa 100644
--- a/include/SFML/Graphics/Color.hpp
+++ b/include/SFML/Graphics/Color.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/ConvexShape.hpp b/include/SFML/Graphics/ConvexShape.hpp
index 117f843..e770299 100644
--- a/include/SFML/Graphics/ConvexShape.hpp
+++ b/include/SFML/Graphics/ConvexShape.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Drawable.hpp b/include/SFML/Graphics/Drawable.hpp
index a409cf7..852b22d 100644
--- a/include/SFML/Graphics/Drawable.hpp
+++ b/include/SFML/Graphics/Drawable.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Export.hpp b/include/SFML/Graphics/Export.hpp
index de164a1..0b47b39 100644
--- a/include/SFML/Graphics/Export.hpp
+++ b/include/SFML/Graphics/Export.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp
index 19c0308..e753866 100644
--- a/include/SFML/Graphics/Font.hpp
+++ b/include/SFML/Graphics/Font.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -91,7 +91,7 @@ public:
///
/// The supported font formats are: TrueType, Type 1, CFF,
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
- /// Note that this function know nothing about the standard
+ /// Note that this function knows nothing about the standard
/// fonts installed on the user's system, thus you can't
/// load them directly.
///
diff --git a/include/SFML/Graphics/Glsl.hpp b/include/SFML/Graphics/Glsl.hpp
index 7bf1604..e3943e7 100644
--- a/include/SFML/Graphics/Glsl.hpp
+++ b/include/SFML/Graphics/Glsl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Glsl.inl b/include/SFML/Graphics/Glsl.inl
index 8e72871..9c9f0ae 100644
--- a/include/SFML/Graphics/Glsl.inl
+++ b/include/SFML/Graphics/Glsl.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Glyph.hpp b/include/SFML/Graphics/Glyph.hpp
index 8c632af..59deb9b 100644
--- a/include/SFML/Graphics/Glyph.hpp
+++ b/include/SFML/Graphics/Glyph.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp
index a9010c0..c1d672a 100644
--- a/include/SFML/Graphics/Image.hpp
+++ b/include/SFML/Graphics/Image.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -265,9 +265,6 @@ private:
////////////////////////////////////////////////////////////
Vector2u m_size; ///< Image size
std::vector<Uint8> m_pixels; ///< Pixels of the image
- #ifdef SFML_SYSTEM_ANDROID
- void* m_stream; ///< Asset file streamer (if loaded from file)
- #endif
};
} // namespace sf
diff --git a/include/SFML/Graphics/PrimitiveType.hpp b/include/SFML/Graphics/PrimitiveType.hpp
index 33f9e46..28cf58d 100644
--- a/include/SFML/Graphics/PrimitiveType.hpp
+++ b/include/SFML/Graphics/PrimitiveType.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Rect.hpp b/include/SFML/Graphics/Rect.hpp
index b88e9b2..17f20a5 100644
--- a/include/SFML/Graphics/Rect.hpp
+++ b/include/SFML/Graphics/Rect.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Rect.inl b/include/SFML/Graphics/Rect.inl
index c1bb9bb..7a82e46 100644
--- a/include/SFML/Graphics/Rect.inl
+++ b/include/SFML/Graphics/Rect.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/RectangleShape.hpp b/include/SFML/Graphics/RectangleShape.hpp
index f9754f6..4f2c4d9 100644
--- a/include/SFML/Graphics/RectangleShape.hpp
+++ b/include/SFML/Graphics/RectangleShape.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/RenderStates.hpp b/include/SFML/Graphics/RenderStates.hpp
index 870b275..9bcde9b 100644
--- a/include/SFML/Graphics/RenderStates.hpp
+++ b/include/SFML/Graphics/RenderStates.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp
index ba842fb..0d16746 100644
--- a/include/SFML/Graphics/RenderTarget.hpp
+++ b/include/SFML/Graphics/RenderTarget.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -43,6 +43,7 @@
namespace sf
{
class Drawable;
+class VertexBuffer;
////////////////////////////////////////////////////////////
/// \brief Base class for all render targets (window, texture, ...)
@@ -248,6 +249,26 @@ public:
PrimitiveType type, const RenderStates& states = RenderStates::Default);
////////////////////////////////////////////////////////////
+ /// \brief Draw primitives defined by a vertex buffer
+ ///
+ /// \param vertexBuffer Vertex buffer
+ /// \param states Render states to use for drawing
+ ///
+ ////////////////////////////////////////////////////////////
+ void draw(const VertexBuffer& vertexBuffer, const RenderStates& states = RenderStates::Default);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Draw primitives defined by a vertex buffer
+ ///
+ /// \param vertexBuffer Vertex buffer
+ /// \param firstVertex Index of the first vertex to render
+ /// \param vertexCount Number of vertices to render
+ /// \param states Render states to use for drawing
+ ///
+ ////////////////////////////////////////////////////////////
+ void draw(const VertexBuffer& vertexBuffer, std::size_t firstVertex, std::size_t vertexCount, const RenderStates& states = RenderStates::Default);
+
+ ////////////////////////////////////////////////////////////
/// \brief Return the size of the rendering region of the target
///
/// \return Size in pixels
@@ -256,6 +277,28 @@ public:
virtual Vector2u getSize() const = 0;
////////////////////////////////////////////////////////////
+ /// \brief Activate or deactivate the render target for rendering
+ ///
+ /// This function makes the render target's context current for
+ /// future OpenGL rendering operations (so you shouldn't care
+ /// about it if you're not doing direct OpenGL stuff).
+ /// A render target's context is active only on the current thread,
+ /// if you want to make it active on another thread you have
+ /// to deactivate it on the previous thread first if it was active.
+ /// Only one context can be current in a thread, so if you
+ /// want to draw OpenGL geometry to another render target
+ /// don't forget to activate it again. Activating a render
+ /// target will automatically deactivate the previously active
+ /// context (if any).
+ ///
+ /// \param active True to activate, false to deactivate
+ ///
+ /// \return True if operation was successful, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual bool setActive(bool active = true);
+
+ ////////////////////////////////////////////////////////////
/// \brief Save the current OpenGL render states and matrices
///
/// This function can be used when you mix SFML drawing
@@ -381,18 +424,31 @@ private:
void applyShader(const Shader* shader);
////////////////////////////////////////////////////////////
- /// \brief Activate the target for rendering
+ /// \brief Setup environment for drawing
///
- /// This function must be implemented by derived classes to make
- /// their OpenGL context current; it is called by the base class
- /// everytime it's going to use OpenGL calls.
+ /// \param useVertexCache Are we going to use the vertex cache?
+ /// \param states Render states to use for drawing
///
- /// \param active True to make the target active, false to deactivate it
+ ////////////////////////////////////////////////////////////
+ void setupDraw(bool useVertexCache, const RenderStates& states);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Draw the primitives
+ ///
+ /// \param type Type of primitives to draw
+ /// \param firstVertex Index of the first vertex to use when drawing
+ /// \param vertexCount Number of vertices to use when drawing
+ ///
+ ////////////////////////////////////////////////////////////
+ void drawPrimitives(PrimitiveType type, std::size_t firstVertex, std::size_t vertexCount);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Clean up environment after drawing
///
- /// \return True if the function succeeded
+ /// \param states Render states used for drawing
///
////////////////////////////////////////////////////////////
- virtual bool activate(bool active) = 0;
+ void cleanupDraw(const RenderStates& states);
////////////////////////////////////////////////////////////
/// \brief Render states cache
@@ -402,10 +458,12 @@ private:
{
enum {VertexCacheSize = 4};
+ bool enable; ///< Is the cache enabled?
bool glStatesSet; ///< Are our internal GL states set yet?
bool viewChanged; ///< Has the current view changed since last draw?
BlendMode lastBlendMode; ///< Cached blending mode
Uint64 lastTextureId; ///< Cached texture
+ bool texCoordsArrayEnabled; ///< Is GL_TEXTURE_COORD_ARRAY client state enabled?
bool useVertexCache; ///< Did we previously use the vertex cache?
Vertex vertexCache[VertexCacheSize]; ///< Pre-transformed vertices cache
};
@@ -416,6 +474,7 @@ private:
View m_defaultView; ///< Default view
View m_view; ///< Current view
StatesCache m_cache; ///< Render states cache
+ Uint64 m_id; ///< Unique number that identifies the RenderTarget
};
} // namespace sf
diff --git a/include/SFML/Graphics/RenderTexture.hpp b/include/SFML/Graphics/RenderTexture.hpp
index db3f91e..a26d94b 100644
--- a/include/SFML/Graphics/RenderTexture.hpp
+++ b/include/SFML/Graphics/RenderTexture.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,7 @@
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
+#include <SFML/Window/ContextSettings.hpp>
namespace sf
@@ -82,8 +83,38 @@ public:
///
/// \return True if creation has been successful
///
+ /// \deprecated Use create(unsigned int, unsigned int, const ContextSettings&) instead.
+ ///
+ ////////////////////////////////////////////////////////////
+ SFML_DEPRECATED bool create(unsigned int width, unsigned int height, bool depthBuffer);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create the render-texture
+ ///
+ /// Before calling this function, the render-texture is in
+ /// an invalid state, thus it is mandatory to call it before
+ /// doing anything with the render-texture.
+ /// The last parameter, \a settings, is useful if you want to enable
+ /// multi-sampling or use the render-texture for OpenGL rendering that
+ /// requires a depth or stencil buffer. Otherwise it is unnecessary, and
+ /// you should leave this parameter at its default value.
+ ///
+ /// \param width Width of the render-texture
+ /// \param height Height of the render-texture
+ /// \param settings Additional settings for the underlying OpenGL texture and context
+ ///
+ /// \return True if creation has been successful
+ ///
////////////////////////////////////////////////////////////
- bool create(unsigned int width, unsigned int height, bool depthBuffer = false);
+ bool create(unsigned int width, unsigned int height, const ContextSettings& settings = ContextSettings());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the maximum anti-aliasing level supported by the system
+ ///
+ /// \return The maximum anti-aliasing level supported by the system
+ ///
+ ////////////////////////////////////////////////////////////
+ static unsigned int getMaximumAntialiasingLevel();
////////////////////////////////////////////////////////////
/// \brief Enable or disable texture smoothing
@@ -205,19 +236,6 @@ public:
private:
////////////////////////////////////////////////////////////
- /// \brief Activate the target for rendering
- ///
- /// This function is called by the base class
- /// everytime it's going to use OpenGL calls.
- ///
- /// \param active True to make the target active, false to deactivate it
- ///
- /// \return True if the function succeeded
- ///
- ////////////////////////////////////////////////////////////
- virtual bool activate(bool active);
-
- ////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
priv::RenderTextureImpl* m_impl; ///< Platform/hardware specific implementation
diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp
index 8b24e1e..2b3b6bc 100644
--- a/include/SFML/Graphics/RenderWindow.hpp
+++ b/include/SFML/Graphics/RenderWindow.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -113,6 +113,24 @@ public:
virtual Vector2u getSize() const;
////////////////////////////////////////////////////////////
+ /// \brief Activate or deactivate the window as the current target
+ /// for OpenGL rendering
+ ///
+ /// A window is active only on the current thread, if you want to
+ /// make it active on another thread you have to deactivate it
+ /// on the previous thread first if it was active.
+ /// Only one window can be active on a thread at a time, thus
+ /// the window previously active (if any) automatically gets deactivated.
+ /// This is not to be confused with requestFocus().
+ ///
+ /// \param active True to activate, false to deactivate
+ ///
+ /// \return True if operation was successful, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ bool setActive(bool active = true);
+
+ ////////////////////////////////////////////////////////////
/// \brief Copy the current contents of the window to an image
///
/// \deprecated
@@ -159,18 +177,6 @@ protected:
///
////////////////////////////////////////////////////////////
virtual void onResize();
-
-private:
-
- ////////////////////////////////////////////////////////////
- /// \brief Activate the target for rendering
- ///
- /// \param active True to make the target active, false to deactivate it
- ///
- /// \return True if the function succeeded
- ///
- ////////////////////////////////////////////////////////////
- virtual bool activate(bool active);
};
} // namespace sf
diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp
index 9fe9c60..664dd86 100644
--- a/include/SFML/Graphics/Shader.hpp
+++ b/include/SFML/Graphics/Shader.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -822,7 +822,7 @@ private:
/// object being drawn (which cannot be known in advance).
///
/// To apply a shader to a drawable, you must pass it as an
-/// additional parameter to the \ref Window::draw() draw() function:
+/// additional parameter to the \ref RenderWindow::draw function:
/// \code
/// window.draw(sprite, &shader);
/// \endcode
diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp
index b257ddc..79ac528 100644
--- a/include/SFML/Graphics/Shape.hpp
+++ b/include/SFML/Graphics/Shape.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp
index 51bba30..55cc898 100644
--- a/include/SFML/Graphics/Sprite.hpp
+++ b/include/SFML/Graphics/Sprite.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Text.hpp b/include/SFML/Graphics/Text.hpp
index f3e389f..dae6ef2 100644
--- a/include/SFML/Graphics/Text.hpp
+++ b/include/SFML/Graphics/Text.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -145,6 +145,39 @@ public:
void setCharacterSize(unsigned int size);
////////////////////////////////////////////////////////////
+ /// \brief Set the line spacing factor
+ ///
+ /// The default spacing between lines is defined by the font.
+ /// This method enables you to set a factor for the spacing
+ /// between lines. By default the line spacing factor is 1.
+ ///
+ /// \param spacingFactor New line spacing factor
+ ///
+ /// \see getLineSpacing
+ ///
+ ////////////////////////////////////////////////////////////
+ void setLineSpacing(float spacingFactor);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the letter spacing factor
+ ///
+ /// The default spacing between letters is defined by the font.
+ /// This factor doesn't directly apply to the existing
+ /// spacing between each character, it rather adds a fixed
+ /// space between them which is calculated from the font
+ /// metrics and the character size.
+ /// Note that factors below 1 (including negative numbers) bring
+ /// characters closer to each other.
+ /// By default the letter spacing factor is 1.
+ ///
+ /// \param spacingFactor New letter spacing factor
+ ///
+ /// \see getLetterSpacing
+ ///
+ ////////////////////////////////////////////////////////////
+ void setLetterSpacing(float spacingFactor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Set the text's style
///
/// You can pass a combination of one or more styles, for
@@ -261,6 +294,26 @@ public:
unsigned int getCharacterSize() const;
////////////////////////////////////////////////////////////
+ /// \brief Get the size of the letter spacing factor
+ ///
+ /// \return Size of the letter spacing factor
+ ///
+ /// \see setLetterSpacing
+ ///
+ ////////////////////////////////////////////////////////////
+ float getLetterSpacing() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the size of the line spacing factor
+ ///
+ /// \return Size of the line spacing factor
+ ///
+ /// \see setLineSpacing
+ ///
+ ////////////////////////////////////////////////////////////
+ float getLineSpacing() const;
+
+ ////////////////////////////////////////////////////////////
/// \brief Get the text's style
///
/// \return Text's style
@@ -382,17 +435,20 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- String m_string; ///< String to display
- const Font* m_font; ///< Font used to display the string
- unsigned int m_characterSize; ///< Base size of characters, in pixels
- Uint32 m_style; ///< Text style (see Style enum)
- Color m_fillColor; ///< Text fill color
- Color m_outlineColor; ///< Text outline color
- float m_outlineThickness; ///< Thickness of the text's outline
- mutable VertexArray m_vertices; ///< Vertex array containing the fill geometry
- mutable VertexArray m_outlineVertices; ///< Vertex array containing the outline geometry
- mutable FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates)
- mutable bool m_geometryNeedUpdate; ///< Does the geometry need to be recomputed?
+ String m_string; ///< String to display
+ const Font* m_font; ///< Font used to display the string
+ unsigned int m_characterSize; ///< Base size of characters, in pixels
+ float m_letterSpacingFactor; ///< Spacing factor between letters
+ float m_lineSpacingFactor; ///< Spacing factor between lines
+ Uint32 m_style; ///< Text style (see Style enum)
+ Color m_fillColor; ///< Text fill color
+ Color m_outlineColor; ///< Text outline color
+ float m_outlineThickness; ///< Thickness of the text's outline
+ mutable VertexArray m_vertices; ///< Vertex array containing the fill geometry
+ mutable VertexArray m_outlineVertices; ///< Vertex array containing the outline geometry
+ mutable FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates)
+ mutable bool m_geometryNeedUpdate; ///< Does the geometry need to be recomputed?
+ mutable Uint64 m_fontTextureId; ///< The font texture id
};
} // namespace sf
@@ -411,8 +467,9 @@ private:
/// It inherits all the functions from sf::Transformable:
/// position, rotation, scale, origin. It also adds text-specific
/// properties such as the font to use, the character size,
-/// the font style (bold, italic, underlined, strike through), the
-/// global color and the text to display of course.
+/// the font style (bold, italic, underlined and strike through), the
+/// text color, the outline thickness, the outline color, the character
+/// spacing, the line spacing and the text to display of course.
/// It also provides convenience functions to calculate the
/// graphical size of the text, or to get the global position
/// of a given character.
@@ -445,7 +502,7 @@ private:
/// sf::Text text("hello", font);
/// text.setCharacterSize(30);
/// text.setStyle(sf::Text::Bold);
-/// text.setColor(sf::Color::Red);
+/// text.setFillColor(sf::Color::Red);
///
/// // Draw it
/// window.draw(text);
diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp
index f88c582..c292856 100644
--- a/include/SFML/Graphics/Texture.hpp
+++ b/include/SFML/Graphics/Texture.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -35,10 +35,11 @@
namespace sf
{
-class Window;
+class InputStream;
class RenderTarget;
class RenderTexture;
-class InputStream;
+class Text;
+class Window;
////////////////////////////////////////////////////////////
/// \brief Image living on the graphics card that can be used for drawing
@@ -277,6 +278,43 @@ public:
void update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y);
////////////////////////////////////////////////////////////
+ /// \brief Update a part of this texture from another texture
+ ///
+ /// Although the source texture can be smaller than this texture,
+ /// this function is usually used for updating the whole texture.
+ /// The other overload, which has (x, y) additional arguments,
+ /// is more convenient for updating a sub-area of this texture.
+ ///
+ /// No additional check is performed on the size of the passed
+ /// texture, passing a texture bigger than this texture
+ /// will lead to an undefined behavior.
+ ///
+ /// This function does nothing if either texture was not
+ /// previously created.
+ ///
+ /// \param texture Source texture to copy to this texture
+ ///
+ ////////////////////////////////////////////////////////////
+ void update(const Texture& texture);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update a part of this texture from another texture
+ ///
+ /// No additional check is performed on the size of the texture,
+ /// passing an invalid combination of texture size and offset
+ /// will lead to an undefined behavior.
+ ///
+ /// This function does nothing if either texture was not
+ /// previously created.
+ ///
+ /// \param texture Source texture to copy to this texture
+ /// \param x X offset in this texture where to copy the source texture
+ /// \param y Y offset in this texture where to copy the source texture
+ ///
+ ////////////////////////////////////////////////////////////
+ void update(const Texture& texture, unsigned int x, unsigned int y);
+
+ ////////////////////////////////////////////////////////////
/// \brief Update the texture from an image
///
/// Although the source image can be smaller than the texture,
@@ -481,6 +519,14 @@ public:
Texture& operator =(const Texture& right);
////////////////////////////////////////////////////////////
+ /// \brief Swap the contents of this texture with those of another
+ ///
+ /// \param right Instance to swap with
+ ///
+ ////////////////////////////////////////////////////////////
+ void swap(Texture& right);
+
+ ////////////////////////////////////////////////////////////
/// \brief Get the underlying OpenGL handle of the texture.
///
/// You shouldn't need to use this function, unless you have
@@ -539,6 +585,7 @@ public:
private:
+ friend class Text;
friend class RenderTexture;
friend class RenderTarget;
diff --git a/include/SFML/Graphics/Transform.hpp b/include/SFML/Graphics/Transform.hpp
index ab0307c..c77d08a 100644
--- a/include/SFML/Graphics/Transform.hpp
+++ b/include/SFML/Graphics/Transform.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -403,6 +403,35 @@ SFML_GRAPHICS_API Transform& operator *=(Transform& left, const Transform& right
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API Vector2f operator *(const Transform& left, const Vector2f& right);
+////////////////////////////////////////////////////////////
+/// \relates sf::Transform
+/// \brief Overload of binary operator == to compare two transforms
+///
+/// Performs an element-wise comparison of the elements of the
+/// left transform with the elements of the right transform.
+///
+/// \param left Left operand (the first transform)
+/// \param right Right operand (the second transform)
+///
+/// \return true if the transforms are equal, false otherwise
+///
+////////////////////////////////////////////////////////////
+SFML_GRAPHICS_API bool operator ==(const Transform& left, const Transform& right);
+
+////////////////////////////////////////////////////////////
+/// \relates sf::Transform
+/// \brief Overload of binary operator != to compare two transforms
+///
+/// This call is equivalent to !(left == right).
+///
+/// \param left Left operand (the first transform)
+/// \param right Right operand (the second transform)
+///
+/// \return true if the transforms are not equal, false otherwise
+///
+////////////////////////////////////////////////////////////
+SFML_GRAPHICS_API bool operator !=(const Transform& left, const Transform& right);
+
} // namespace sf
diff --git a/include/SFML/Graphics/Transformable.hpp b/include/SFML/Graphics/Transformable.hpp
index 4e46cc6..67a5656 100644
--- a/include/SFML/Graphics/Transformable.hpp
+++ b/include/SFML/Graphics/Transformable.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/Vertex.hpp b/include/SFML/Graphics/Vertex.hpp
index a9a8820..bb24448 100644
--- a/include/SFML/Graphics/Vertex.hpp
+++ b/include/SFML/Graphics/Vertex.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/VertexArray.hpp b/include/SFML/Graphics/VertexArray.hpp
index 109a7e8..5229065 100644
--- a/include/SFML/Graphics/VertexArray.hpp
+++ b/include/SFML/Graphics/VertexArray.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Graphics/VertexBuffer.hpp b/include/SFML/Graphics/VertexBuffer.hpp
new file mode 100644
index 0000000..a91a08f
--- /dev/null
+++ b/include/SFML/Graphics/VertexBuffer.hpp
@@ -0,0 +1,408 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_VERTEXBUFFER_HPP
+#define SFML_VERTEXBUFFER_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Graphics/Export.hpp>
+#include <SFML/Graphics/PrimitiveType.hpp>
+#include <SFML/Graphics/Drawable.hpp>
+#include <SFML/Window/GlResource.hpp>
+
+
+namespace sf
+{
+class RenderTarget;
+class Vertex;
+
+////////////////////////////////////////////////////////////
+/// \brief Vertex buffer storage for one or more 2D primitives
+///
+////////////////////////////////////////////////////////////
+class SFML_GRAPHICS_API VertexBuffer : public Drawable, private GlResource
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Usage specifiers
+ ///
+ /// If data is going to be updated once or more every frame,
+ /// set the usage to Stream. If data is going to be set once
+ /// and used for a long time without being modified, set the
+ /// usage to Static. For everything else Dynamic should be a
+ /// good compromise.
+ ///
+ ////////////////////////////////////////////////////////////
+ enum Usage
+ {
+ Stream, ///< Constantly changing data
+ Dynamic, ///< Occasionally changing data
+ Static ///< Rarely changing data
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Creates an empty vertex buffer.
+ ///
+ ////////////////////////////////////////////////////////////
+ VertexBuffer();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct a VertexBuffer with a specific PrimitiveType
+ ///
+ /// Creates an empty vertex buffer and sets its primitive type to \p type.
+ ///
+ /// \param type Type of primitive
+ ///
+ ////////////////////////////////////////////////////////////
+ explicit VertexBuffer(PrimitiveType type);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct a VertexBuffer with a specific usage specifier
+ ///
+ /// Creates an empty vertex buffer and sets its usage to \p usage.
+ ///
+ /// \param usage Usage specifier
+ ///
+ ////////////////////////////////////////////////////////////
+ explicit VertexBuffer(Usage usage);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct a VertexBuffer with a specific PrimitiveType and usage specifier
+ ///
+ /// Creates an empty vertex buffer and sets its primitive type
+ /// to \p type and usage to \p usage.
+ ///
+ /// \param type Type of primitive
+ /// \param usage Usage specifier
+ ///
+ ////////////////////////////////////////////////////////////
+ VertexBuffer(PrimitiveType type, Usage usage);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Copy constructor
+ ///
+ /// \param copy instance to copy
+ ///
+ ////////////////////////////////////////////////////////////
+ VertexBuffer(const VertexBuffer& copy);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~VertexBuffer();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create the vertex buffer
+ ///
+ /// Creates the vertex buffer and allocates enough graphics
+ /// memory to hold \p vertexCount vertices. Any previously
+ /// allocated memory is freed in the process.
+ ///
+ /// In order to deallocate previously allocated memory pass 0
+ /// as \p vertexCount. Don't forget to recreate with a non-zero
+ /// value when graphics memory should be allocated again.
+ ///
+ /// \param vertexCount Number of vertices worth of memory to allocate
+ ///
+ /// \return True if creation was successful
+ ///
+ ////////////////////////////////////////////////////////////
+ bool create(std::size_t vertexCount);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Return the vertex count
+ ///
+ /// \return Number of vertices in the vertex buffer
+ ///
+ ////////////////////////////////////////////////////////////
+ std::size_t getVertexCount() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the whole buffer from an array of vertices
+ ///
+ /// The \a vertex array is assumed to have the same size as
+ /// the \a created buffer.
+ ///
+ /// No additional check is performed on the size of the vertex
+ /// array, passing invalid arguments will lead to undefined
+ /// behavior.
+ ///
+ /// This function does nothing if \a vertices is null or if the
+ /// buffer was not previously created.
+ ///
+ /// \param vertices Array of vertices to copy to the buffer
+ ///
+ /// \return True if the update was successful
+ ///
+ ////////////////////////////////////////////////////////////
+ bool update(const Vertex* vertices);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update a part of the buffer from an array of vertices
+ ///
+ /// \p offset is specified as the number of vertices to skip
+ /// from the beginning of the buffer.
+ ///
+ /// If \p offset is 0 and \p vertexCount is equal to the size of
+ /// the currently created buffer, its whole contents are replaced.
+ ///
+ /// If \p offset is 0 and \p vertexCount is greater than the
+ /// size of the currently created buffer, a new buffer is created
+ /// containing the vertex data.
+ ///
+ /// If \p offset is 0 and \p vertexCount is less than the size of
+ /// the currently created buffer, only the corresponding region
+ /// is updated.
+ ///
+ /// If \p offset is not 0 and \p offset + \p vertexCount is greater
+ /// than the size of the currently created buffer, the update fails.
+ ///
+ /// No additional check is performed on the size of the vertex
+ /// array, passing invalid arguments will lead to undefined
+ /// behavior.
+ ///
+ /// \param vertices Array of vertices to copy to the buffer
+ /// \param vertexCount Number of vertices to copy
+ /// \param offset Offset in the buffer to copy to
+ ///
+ /// \return True if the update was successful
+ ///
+ ////////////////////////////////////////////////////////////
+ bool update(const Vertex* vertices, std::size_t vertexCount, unsigned int offset);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Copy the contents of another buffer into this buffer
+ ///
+ /// \param vertexBuffer Vertex buffer whose contents to copy into this vertex buffer
+ ///
+ /// \return True if the copy was successful
+ ///
+ ////////////////////////////////////////////////////////////
+ bool update(const VertexBuffer& vertexBuffer);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Overload of assignment operator
+ ///
+ /// \param right Instance to assign
+ ///
+ /// \return Reference to self
+ ///
+ ////////////////////////////////////////////////////////////
+ VertexBuffer& operator =(const VertexBuffer& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Swap the contents of this vertex buffer with those of another
+ ///
+ /// \param right Instance to swap with
+ ///
+ ////////////////////////////////////////////////////////////
+ void swap(VertexBuffer& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the underlying OpenGL handle of the vertex buffer.
+ ///
+ /// You shouldn't need to use this function, unless you have
+ /// very specific stuff to implement that SFML doesn't support,
+ /// or implement a temporary workaround until a bug is fixed.
+ ///
+ /// \return OpenGL handle of the vertex buffer or 0 if not yet created
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int getNativeHandle() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the type of primitives to draw
+ ///
+ /// This function defines how the vertices must be interpreted
+ /// when it's time to draw them.
+ ///
+ /// The default primitive type is sf::Points.
+ ///
+ /// \param type Type of primitive
+ ///
+ ////////////////////////////////////////////////////////////
+ void setPrimitiveType(PrimitiveType type);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the type of primitives drawn by the vertex buffer
+ ///
+ /// \return Primitive type
+ ///
+ ////////////////////////////////////////////////////////////
+ PrimitiveType getPrimitiveType() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the usage specifier of this vertex buffer
+ ///
+ /// This function provides a hint about how this vertex buffer is
+ /// going to be used in terms of data update frequency.
+ ///
+ /// After changing the usage specifier, the vertex buffer has
+ /// to be updated with new data for the usage specifier to
+ /// take effect.
+ ///
+ /// The default primitive type is sf::VertexBuffer::Stream.
+ ///
+ /// \param usage Usage specifier
+ ///
+ ////////////////////////////////////////////////////////////
+ void setUsage(Usage usage);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the usage specifier of this vertex buffer
+ ///
+ /// \return Usage specifier
+ ///
+ ////////////////////////////////////////////////////////////
+ Usage getUsage() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Bind a vertex buffer for rendering
+ ///
+ /// This function is not part of the graphics API, it mustn't be
+ /// used when drawing SFML entities. It must be used only if you
+ /// mix sf::VertexBuffer with OpenGL code.
+ ///
+ /// \code
+ /// sf::VertexBuffer vb1, vb2;
+ /// ...
+ /// sf::VertexBuffer::bind(&vb1);
+ /// // draw OpenGL stuff that use vb1...
+ /// sf::VertexBuffer::bind(&vb2);
+ /// // draw OpenGL stuff that use vb2...
+ /// sf::VertexBuffer::bind(NULL);
+ /// // draw OpenGL stuff that use no vertex buffer...
+ /// \endcode
+ ///
+ /// \param vertexBuffer Pointer to the vertex buffer to bind, can be null to use no vertex buffer
+ ///
+ ////////////////////////////////////////////////////////////
+ static void bind(const VertexBuffer* vertexBuffer);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Tell whether or not the system supports vertex buffers
+ ///
+ /// This function should always be called before using
+ /// the vertex buffer features. If it returns false, then
+ /// any attempt to use sf::VertexBuffer will fail.
+ ///
+ /// \return True if vertex buffers are supported, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool isAvailable();
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Draw the vertex buffer to a render target
+ ///
+ /// \param target Render target to draw to
+ /// \param states Current render states
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void draw(RenderTarget& target, RenderStates states) const;
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ unsigned int m_buffer; ///< Internal buffer identifier
+ std::size_t m_size; ///< Size in Vertexes of the currently allocated buffer
+ PrimitiveType m_primitiveType; ///< Type of primitives to draw
+ Usage m_usage; ///< How this vertex buffer is to be used
+};
+
+} // namespace sf
+
+
+#endif // SFML_VERTEXBUFFER_HPP
+
+
+////////////////////////////////////////////////////////////
+/// \class sf::VertexBuffer
+/// \ingroup graphics
+///
+/// sf::VertexBuffer is a simple wrapper around a dynamic
+/// buffer of vertices and a primitives type.
+///
+/// Unlike sf::VertexArray, the vertex data is stored in
+/// graphics memory.
+///
+/// In situations where a large amount of vertex data would
+/// have to be transferred from system memory to graphics memory
+/// every frame, using sf::VertexBuffer can help. By using a
+/// sf::VertexBuffer, data that has not been changed between frames
+/// does not have to be re-transferred from system to graphics
+/// memory as would be the case with sf::VertexArray. If data transfer
+/// is a bottleneck, this can lead to performance gains.
+///
+/// Using sf::VertexBuffer, the user also has the ability to only modify
+/// a portion of the buffer in graphics memory. This way, a large buffer
+/// can be allocated at the start of the application and only the
+/// applicable portions of it need to be updated during the course of
+/// the application. This allows the user to take full control of data
+/// transfers between system and graphics memory if they need to.
+///
+/// In special cases, the user can make use of multiple threads to update
+/// vertex data in multiple distinct regions of the buffer simultaneously.
+/// This might make sense when e.g. the position of multiple objects has to
+/// be recalculated very frequently. The computation load can be spread
+/// across multiple threads as long as there are no other data dependencies.
+///
+/// Simultaneous updates to the vertex buffer are not guaranteed to be
+/// carried out by the driver in any specific order. Updating the same
+/// region of the buffer from multiple threads will not cause undefined
+/// behaviour, however the final state of the buffer will be unpredictable.
+///
+/// Simultaneous updates of distinct non-overlapping regions of the buffer
+/// are also not guaranteed to complete in a specific order. However, in
+/// this case the user can make sure to synchronize the writer threads at
+/// well-defined points in their code. The driver will make sure that all
+/// pending data transfers complete before the vertex buffer is sourced
+/// by the rendering pipeline.
+///
+/// It inherits sf::Drawable, but unlike other drawables it
+/// is not transformable.
+///
+/// Example:
+/// \code
+/// sf::Vertex vertices[15];
+/// ...
+/// sf::VertexBuffer triangles(sf::Triangles);
+/// triangles.create(15);
+/// triangles.update(vertices);
+/// ...
+/// window.draw(triangles);
+/// \endcode
+///
+/// \see sf::Vertex, sf::VertexArray
+///
+////////////////////////////////////////////////////////////
diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp
index d49cb49..a3faa6e 100644
--- a/include/SFML/Graphics/View.hpp
+++ b/include/SFML/Graphics/View.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Main.hpp b/include/SFML/Main.hpp
index f8ac048..c28a7e1 100644
--- a/include/SFML/Main.hpp
+++ b/include/SFML/Main.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network.hpp b/include/SFML/Network.hpp
index 3216c5c..ccc9f7c 100644
--- a/include/SFML/Network.hpp
+++ b/include/SFML/Network.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/Export.hpp b/include/SFML/Network/Export.hpp
index 4a8d800..e7ebdd4 100644
--- a/include/SFML/Network/Export.hpp
+++ b/include/SFML/Network/Export.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/Ftp.hpp b/include/SFML/Network/Ftp.hpp
index 3600a9d..ee779cc 100644
--- a/include/SFML/Network/Ftp.hpp
+++ b/include/SFML/Network/Ftp.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -475,16 +475,20 @@ public:
/// remote path is relative to the current directory of the
/// FTP server.
///
+ /// The append parameter controls whether the remote file is
+ /// appended to or overwritten if it already exists.
+ ///
/// \param localFile Path of the local file to upload
/// \param remotePath The directory in which to put the file on the server
/// \param mode Transfer mode
+ /// \param append Pass true to append to or false to overwrite the remote file if it already exists
///
/// \return Server response to the request
///
/// \see download
///
////////////////////////////////////////////////////////////
- Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary);
+ Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary, bool append = false);
////////////////////////////////////////////////////////////
/// \brief Send a command to the FTP server
diff --git a/include/SFML/Network/Http.hpp b/include/SFML/Network/Http.hpp
index d165a7c..44fe67d 100644
--- a/include/SFML/Network/Http.hpp
+++ b/include/SFML/Network/Http.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/IpAddress.hpp b/include/SFML/Network/IpAddress.hpp
index 4940f2b..9ec13c4 100644
--- a/include/SFML/Network/IpAddress.hpp
+++ b/include/SFML/Network/IpAddress.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/Packet.hpp b/include/SFML/Network/Packet.hpp
index ac97692..9f0edab 100644
--- a/include/SFML/Network/Packet.hpp
+++ b/include/SFML/Network/Packet.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -171,45 +171,165 @@ public:
operator BoolType() const;
////////////////////////////////////////////////////////////
- /// Overloads of operator >> to read data from the packet
+ /// Overload of operator >> to read data from the packet
///
////////////////////////////////////////////////////////////
Packet& operator >>(bool& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Int8& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Uint8& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Int16& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Uint16& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Int32& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Uint32& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Int64& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(Uint64& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(float& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(double& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(char* data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(std::string& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(wchar_t* data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(std::wstring& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator >>(String& data);
////////////////////////////////////////////////////////////
- /// Overloads of operator << to write data into the packet
+ /// Overload of operator << to write data into the packet
///
////////////////////////////////////////////////////////////
Packet& operator <<(bool data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Int8 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Uint8 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Int16 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Uint16 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Int32 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Uint32 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Int64 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(Uint64 data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(float data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(double data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(const char* data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(const std::string& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(const wchar_t* data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(const std::wstring& data);
+
+ ////////////////////////////////////////////////////////////
+ /// \overload
+ ////////////////////////////////////////////////////////////
Packet& operator <<(const String& data);
protected:
diff --git a/include/SFML/Network/Socket.hpp b/include/SFML/Network/Socket.hpp
index 0b11171..d260174 100644
--- a/include/SFML/Network/Socket.hpp
+++ b/include/SFML/Network/Socket.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/SocketHandle.hpp b/include/SFML/Network/SocketHandle.hpp
index d5b395d..270201b 100644
--- a/include/SFML/Network/SocketHandle.hpp
+++ b/include/SFML/Network/SocketHandle.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/SocketSelector.hpp b/include/SFML/Network/SocketSelector.hpp
index 92dcbad..106d708 100644
--- a/include/SFML/Network/SocketSelector.hpp
+++ b/include/SFML/Network/SocketSelector.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Network/TcpListener.hpp b/include/SFML/Network/TcpListener.hpp
index 720ebf1..e0e05d6 100644
--- a/include/SFML/Network/TcpListener.hpp
+++ b/include/SFML/Network/TcpListener.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -65,14 +65,16 @@ public:
unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
- /// \brief Start listening for connections
+ /// \brief Start listening for incoming connection attempts
///
- /// This functions makes the socket listen to the specified
- /// port, waiting for new connections.
- /// If the socket was previously listening to another port,
- /// it will be stopped first and bound to the new port.
+ /// This function makes the socket start listening on the
+ /// specified port, waiting for incoming connection attempts.
///
- /// \param port Port to listen for new connections
+ /// If the socket is already listening on a port when this
+ /// function is called, it will stop listening on the old
+ /// port before starting to listen on the new port.
+ ///
+ /// \param port Port to listen on for incoming connection attempts
/// \param address Address of the interface to listen on
///
/// \return Status code
diff --git a/include/SFML/Network/TcpSocket.hpp b/include/SFML/Network/TcpSocket.hpp
index da6b549..6c0ab98 100644
--- a/include/SFML/Network/TcpSocket.hpp
+++ b/include/SFML/Network/TcpSocket.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -97,7 +97,8 @@ public:
/// In blocking mode, this function may take a while, especially
/// if the remote peer is not reachable. The last parameter allows
/// you to stop trying to connect after a given timeout.
- /// If the socket was previously connected, it is first disconnected.
+ /// If the socket is already connected, the connection is
+ /// forcibly disconnected before attempting to connect again.
///
/// \param remoteAddress Address of the remote peer
/// \param remotePort Port of the remote peer
diff --git a/include/SFML/Network/UdpSocket.hpp b/include/SFML/Network/UdpSocket.hpp
index 6ee191c..7ce3fe5 100644
--- a/include/SFML/Network/UdpSocket.hpp
+++ b/include/SFML/Network/UdpSocket.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -82,6 +82,11 @@ public:
/// system to automatically pick an available port, and then
/// call getLocalPort to retrieve the chosen port.
///
+ /// Since the socket can only be bound to a single port at
+ /// any given moment, if it is already bound when this
+ /// function is called, it will be unbound from the previous
+ /// port before being bound to the new one.
+ ///
/// \param port Port to bind the socket to
/// \param address Address of the interface to bind to
///
diff --git a/include/SFML/OpenGL.hpp b/include/SFML/OpenGL.hpp
index 39e97b6..6db5d01 100644
--- a/include/SFML/OpenGL.hpp
+++ b/include/SFML/OpenGL.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -45,7 +45,7 @@
#include <GL/gl.h>
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
#if defined(SFML_OPENGL_ES)
#include <GLES/gl.h>
@@ -69,6 +69,7 @@
#include <GLES/glext.h>
// We're not using OpenGL ES 2+ yet, but we can use the sRGB extension
+ #include <GLES2/gl2platform.h>
#include <GLES2/gl2ext.h>
#endif
diff --git a/include/SFML/System.hpp b/include/SFML/System.hpp
index 5f18f76..fa4f9c9 100644
--- a/include/SFML/System.hpp
+++ b/include/SFML/System.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Clock.hpp b/include/SFML/System/Clock.hpp
index 0e57d60..391e2c4 100644
--- a/include/SFML/System/Clock.hpp
+++ b/include/SFML/System/Clock.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Err.hpp b/include/SFML/System/Err.hpp
index 56505a9..a701fef 100644
--- a/include/SFML/System/Err.hpp
+++ b/include/SFML/System/Err.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Export.hpp b/include/SFML/System/Export.hpp
index 0387c2e..e9c8ef8 100644
--- a/include/SFML/System/Export.hpp
+++ b/include/SFML/System/Export.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/FileInputStream.hpp b/include/SFML/System/FileInputStream.hpp
index b1a8c62..43618da 100644
--- a/include/SFML/System/FileInputStream.hpp
+++ b/include/SFML/System/FileInputStream.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/InputStream.hpp b/include/SFML/System/InputStream.hpp
index 4419a0b..495a4b9 100644
--- a/include/SFML/System/InputStream.hpp
+++ b/include/SFML/System/InputStream.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Lock.hpp b/include/SFML/System/Lock.hpp
index eb420a8..906016c 100644
--- a/include/SFML/System/Lock.hpp
+++ b/include/SFML/System/Lock.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/MemoryInputStream.hpp b/include/SFML/System/MemoryInputStream.hpp
index c26f823..4b7f9ef 100644
--- a/include/SFML/System/MemoryInputStream.hpp
+++ b/include/SFML/System/MemoryInputStream.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Mutex.hpp b/include/SFML/System/Mutex.hpp
index 18349e4..eda6909 100644
--- a/include/SFML/System/Mutex.hpp
+++ b/include/SFML/System/Mutex.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/NativeActivity.hpp b/include/SFML/System/NativeActivity.hpp
index 7927620..e8a3b17 100644
--- a/include/SFML/System/NativeActivity.hpp
+++ b/include/SFML/System/NativeActivity.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/NonCopyable.hpp b/include/SFML/System/NonCopyable.hpp
index 7a483bc..dbe1eeb 100644
--- a/include/SFML/System/NonCopyable.hpp
+++ b/include/SFML/System/NonCopyable.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -51,6 +51,16 @@ protected:
///
////////////////////////////////////////////////////////////
NonCopyable() {}
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default destructor
+ ///
+ /// By declaring a protected destructor it's impossible to
+ /// call delete on a pointer of sf::NonCopyable, thus
+ /// preventing possible resource leaks.
+ ///
+ ////////////////////////////////////////////////////////////
+ ~NonCopyable() {}
private:
diff --git a/include/SFML/System/Sleep.hpp b/include/SFML/System/Sleep.hpp
index e943aa1..ac3144b 100644
--- a/include/SFML/System/Sleep.hpp
+++ b/include/SFML/System/Sleep.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/String.hpp b/include/SFML/System/String.hpp
index 8b0da3f..5d047e2 100644
--- a/include/SFML/System/String.hpp
+++ b/include/SFML/System/String.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/String.inl b/include/SFML/System/String.inl
index 1be1266..b8893e7 100644
--- a/include/SFML/System/String.inl
+++ b/include/SFML/System/String.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Thread.hpp b/include/SFML/System/Thread.hpp
index 65c9127..15ae4a5 100644
--- a/include/SFML/System/Thread.hpp
+++ b/include/SFML/System/Thread.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Thread.inl b/include/SFML/System/Thread.inl
index b707aa3..1f2e8de 100644
--- a/include/SFML/System/Thread.inl
+++ b/include/SFML/System/Thread.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/ThreadLocal.hpp b/include/SFML/System/ThreadLocal.hpp
index 6975e52..1ace1ba 100644
--- a/include/SFML/System/ThreadLocal.hpp
+++ b/include/SFML/System/ThreadLocal.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/ThreadLocalPtr.hpp b/include/SFML/System/ThreadLocalPtr.hpp
index 751a9b5..bee944d 100644
--- a/include/SFML/System/ThreadLocalPtr.hpp
+++ b/include/SFML/System/ThreadLocalPtr.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/ThreadLocalPtr.inl b/include/SFML/System/ThreadLocalPtr.inl
index 5652f56..12c7690 100644
--- a/include/SFML/System/ThreadLocalPtr.inl
+++ b/include/SFML/System/ThreadLocalPtr.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Time.hpp b/include/SFML/System/Time.hpp
index 4dff928..43d7548 100644
--- a/include/SFML/System/Time.hpp
+++ b/include/SFML/System/Time.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Utf.hpp b/include/SFML/System/Utf.hpp
index 819d8ff..e1e78f6 100644
--- a/include/SFML/System/Utf.hpp
+++ b/include/SFML/System/Utf.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Utf.inl b/include/SFML/System/Utf.inl
index 6ffceda..67fad8b 100644
--- a/include/SFML/System/Utf.inl
+++ b/include/SFML/System/Utf.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -26,10 +26,10 @@
////////////////////////////////////////////////////////////
// References:
//
-// http://www.unicode.org/
-// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
-// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
-// http://people.w3.org/rishida/scripts/uniview/conversion
+// https://www.unicode.org/
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
+// https://people.w3.org/rishida/scripts/uniview/conversion
//
////////////////////////////////////////////////////////////
diff --git a/include/SFML/System/Vector2.hpp b/include/SFML/System/Vector2.hpp
index d5e1744..237f214 100644
--- a/include/SFML/System/Vector2.hpp
+++ b/include/SFML/System/Vector2.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Vector2.inl b/include/SFML/System/Vector2.inl
index 081b211..29ad76f 100644
--- a/include/SFML/System/Vector2.inl
+++ b/include/SFML/System/Vector2.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Vector3.hpp b/include/SFML/System/Vector3.hpp
index 61d0dc7..b12b2f5 100644
--- a/include/SFML/System/Vector3.hpp
+++ b/include/SFML/System/Vector3.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/System/Vector3.inl b/include/SFML/System/Vector3.inl
index 2f5eea8..b532fe0 100644
--- a/include/SFML/System/Vector3.inl
+++ b/include/SFML/System/Vector3.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window.hpp b/include/SFML/Window.hpp
index eefe267..836f13a 100644
--- a/include/SFML/Window.hpp
+++ b/include/SFML/Window.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -30,8 +30,10 @@
////////////////////////////////////////////////////////////
#include <SFML/System.hpp>
+#include <SFML/Window/Clipboard.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/ContextSettings.hpp>
+#include <SFML/Window/Cursor.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Window/Joystick.hpp>
#include <SFML/Window/Keyboard.hpp>
diff --git a/include/SFML/Window/Clipboard.hpp b/include/SFML/Window/Clipboard.hpp
new file mode 100644
index 0000000..436da8f
--- /dev/null
+++ b/include/SFML/Window/Clipboard.hpp
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARD_HPP
+#define SFML_CLIPBOARD_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Export.hpp>
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class SFML_WINDOW_API Clipboard
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Clipboard contents as sf::String object
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARD_HPP
+
+
+////////////////////////////////////////////////////////////
+/// \class sf::Clipboard
+/// \ingroup window
+///
+/// sf::Clipboard provides an interface for getting and
+/// setting the contents of the system clipboard.
+///
+/// Usage example:
+/// \code
+/// // get the clipboard content as a string
+/// sf::String string = sf::Clipboard::getString();
+///
+/// // or use it in the event loop
+/// sf::Event event;
+/// while(window.pollEvent(event))
+/// {
+/// if(event.type == sf::Event::Closed)
+/// window.close();
+/// if(event.type == sf::Event::KeyPressed)
+/// {
+/// // Using Ctrl + V to paste a string into SFML
+/// if(event.key.control && event.key.code == sf::Keyboard::V)
+/// string = sf::Clipboard::getString();
+/// }
+/// }
+///
+/// // set the clipboard to a string
+/// sf::Clipboard::setString("Hello World!");
+/// \endcode
+///
+/// \see sf::String, sf::Event
+///
+////////////////////////////////////////////////////////////
diff --git a/include/SFML/Window/Context.hpp b/include/SFML/Window/Context.hpp
index 9e1eedd..71e2c0a 100644
--- a/include/SFML/Window/Context.hpp
+++ b/include/SFML/Window/Context.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -112,12 +112,27 @@ public:
////////////////////////////////////////////////////////////
/// \brief Get the currently active context
///
+ /// This function will only return sf::Context objects.
+ /// Contexts created e.g. by RenderTargets or for internal
+ /// use will not be returned by this function.
+ ///
/// \return The currently active context or NULL if none is active
///
////////////////////////////////////////////////////////////
static const Context* getActiveContext();
////////////////////////////////////////////////////////////
+ /// \brief Get the currently active context's ID
+ ///
+ /// The context ID is used to identify contexts when
+ /// managing unshareable OpenGL resources.
+ ///
+ /// \return The active context's ID or 0 if no context is currently active
+ ///
+ ////////////////////////////////////////////////////////////
+ static Uint64 getActiveContextId();
+
+ ////////////////////////////////////////////////////////////
/// \brief Construct a in-memory context
///
/// This constructor is for internal use, you don't need
diff --git a/include/SFML/Window/ContextSettings.hpp b/include/SFML/Window/ContextSettings.hpp
index 2774302..00afbc4 100644
--- a/include/SFML/Window/ContextSettings.hpp
+++ b/include/SFML/Window/ContextSettings.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -25,6 +25,7 @@
#ifndef SFML_CONTEXTSETTINGS_HPP
#define SFML_CONTEXTSETTINGS_HPP
+#include <SFML/Config.hpp>
namespace sf
{
diff --git a/include/SFML/Window/Cursor.hpp b/include/SFML/Window/Cursor.hpp
new file mode 100644
index 0000000..30aebd4
--- /dev/null
+++ b/include/SFML/Window/Cursor.hpp
@@ -0,0 +1,219 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSOR_HPP
+#define SFML_CURSOR_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Export.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+
+namespace sf
+{
+namespace priv
+{
+ class CursorImpl;
+}
+
+////////////////////////////////////////////////////////////
+/// \brief Cursor defines the appearance of a system cursor
+///
+////////////////////////////////////////////////////////////
+class SFML_WINDOW_API Cursor : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Enumeration of the native system cursor types
+ ///
+ /// Refer to the following table to determine which cursor
+ /// is available on which platform.
+ ///
+ /// Type | Linux | Mac OS X | Windows |
+ /// ------------------------------------|:-----:|:--------:|:--------:|
+ /// sf::Cursor::Arrow | yes | yes | yes |
+ /// sf::Cursor::ArrowWait | no | no | yes |
+ /// sf::Cursor::Wait | yes | no | yes |
+ /// sf::Cursor::Text | yes | yes | yes |
+ /// sf::Cursor::Hand | yes | yes | yes |
+ /// sf::Cursor::SizeHorizontal | yes | yes | yes |
+ /// sf::Cursor::SizeVertical | yes | yes | yes |
+ /// sf::Cursor::SizeTopLeftBottomRight | no | no | yes |
+ /// sf::Cursor::SizeBottomLeftTopRight | no | no | yes |
+ /// sf::Cursor::SizeAll | yes | no | yes |
+ /// sf::Cursor::Cross | yes | yes | yes |
+ /// sf::Cursor::Help | yes | no | yes |
+ /// sf::Cursor::NotAllowed | yes | yes | yes |
+ ///
+ ////////////////////////////////////////////////////////////
+ enum Type
+ {
+ Arrow, ///< Arrow cursor (default)
+ ArrowWait, ///< Busy arrow cursor
+ Wait, ///< Busy cursor
+ Text, ///< I-beam, cursor when hovering over a field allowing text entry
+ Hand, ///< Pointing hand cursor
+ SizeHorizontal, ///< Horizontal double arrow cursor
+ SizeVertical, ///< Vertical double arrow cursor
+ SizeTopLeftBottomRight, ///< Double arrow cursor going from top-left to bottom-right
+ SizeBottomLeftTopRight, ///< Double arrow cursor going from bottom-left to top-right
+ SizeAll, ///< Combination of SizeHorizontal and SizeVertical
+ Cross, ///< Crosshair cursor
+ Help, ///< Help cursor
+ NotAllowed ///< Action not allowed cursor
+ };
+
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// This constructor doesn't actually create the cursor;
+ /// initially the new instance is invalid and must not be
+ /// used until either loadFromPixels() or loadFromSystem()
+ /// is called and successfully created a cursor.
+ ///
+ ////////////////////////////////////////////////////////////
+ Cursor();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// This destructor releases the system resources
+ /// associated with this cursor, if any.
+ ///
+ ////////////////////////////////////////////////////////////
+ ~Cursor();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// \a pixels must be an array of \a width by \a height pixels
+ /// in 32-bit RGBA format. If not, this will cause undefined behavior.
+ ///
+ /// If \a pixels is null or either \a width or \a height are 0,
+ /// the current cursor is left unchanged and the function will
+ /// return false.
+ ///
+ /// In addition to specifying the pixel data, you can also
+ /// specify the location of the hotspot of the cursor. The
+ /// hotspot is the pixel coordinate within the cursor image
+ /// which will be located exactly where the mouse pointer
+ /// position is. Any mouse actions that are performed will
+ /// return the window/screen location of the hotspot.
+ ///
+ /// \warning On Unix, the pixels are mapped into a monochrome
+ /// bitmap: pixels with an alpha channel to 0 are
+ /// transparent, black if the RGB channel are close
+ /// to zero, and white otherwise.
+ ///
+ /// \param pixels Array of pixels of the image
+ /// \param size Width and height of the image
+ /// \param hotspot (x,y) location of the hotspot
+ /// \return true if the cursor was successfully loaded;
+ /// false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Refer to the list of cursor available on each system
+ /// (see sf::Cursor::Type) to know whether a given cursor is
+ /// expected to load successfully or is not supported by
+ /// the operating system.
+ ///
+ /// \param type Native system cursor type
+ /// \return true if and only if the corresponding cursor is
+ /// natively supported by the operating system;
+ /// false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Type type);
+
+private:
+
+ friend class Window;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get access to the underlying implementation
+ ///
+ /// This is primarily designed for sf::Window::setMouseCursor,
+ /// hence the friendship.
+ ///
+ /// \return a reference to the OS-specific implementation
+ ///
+ ////////////////////////////////////////////////////////////
+ const priv::CursorImpl& getImpl() const;
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ priv::CursorImpl* m_impl; ///< Platform-specific implementation of the cursor
+};
+
+} // namespace sf
+
+
+#endif // SFML_CURSOR_HPP
+
+
+////////////////////////////////////////////////////////////
+/// \class sf::Cursor
+/// \ingroup window
+///
+/// \warning Features related to Cursor are not supported on
+/// iOS and Android.
+///
+/// This class abstracts the operating system resources
+/// associated with either a native system cursor or a custom
+/// cursor.
+///
+/// After loading the cursor the graphical appearance
+/// with either loadFromPixels() or loadFromSystem(), the
+/// cursor can be changed with sf::Window::setMouseCursor().
+///
+/// The behaviour is undefined if the cursor is destroyed while
+/// in use by the window.
+///
+/// Usage example:
+/// \code
+/// sf::Window window;
+///
+/// // ... create window as usual ...
+///
+/// sf::Cursor cursor;
+/// if (cursor.loadFromSystem(sf::Cursor::Hand))
+/// window.setMouseCursor(cursor);
+/// \endcode
+///
+/// \see sf::Window::setMouseCursor
+///
+////////////////////////////////////////////////////////////
diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp
index 7bfd610..9261785 100644
--- a/include/SFML/Window/Event.hpp
+++ b/include/SFML/Window/Event.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -257,7 +257,7 @@ public:
/// filled; all other members will have undefined values and must not
/// be read if the type of the event doesn't match. For example,
/// if you received a KeyPressed event, then you must read the
-/// event.key member, all other members such as event.MouseMove
+/// event.key member, all other members such as event.mouseMove
/// or event.text will have undefined values.
///
/// Usage example:
diff --git a/include/SFML/Window/Export.hpp b/include/SFML/Window/Export.hpp
index a890bee..37826a2 100644
--- a/include/SFML/Window/Export.hpp
+++ b/include/SFML/Window/Export.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/GlResource.hpp b/include/SFML/Window/GlResource.hpp
index d386c08..f701242 100644
--- a/include/SFML/Window/GlResource.hpp
+++ b/include/SFML/Window/GlResource.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -37,6 +37,8 @@ namespace sf
class Context;
+typedef void(*ContextDestroyCallback)(void*);
+
////////////////////////////////////////////////////////////
/// \brief Base class for classes that require an OpenGL context
///
@@ -58,10 +60,17 @@ protected:
~GlResource();
////////////////////////////////////////////////////////////
- /// \brief Empty function for ABI compatibility, use acquireTransientContext instead
+ /// \brief Register a function to be called when a context is destroyed
+ ///
+ /// This is used for internal purposes in order to properly
+ /// clean up OpenGL resources that cannot be shared between
+ /// contexts.
+ ///
+ /// \param callback Function to be called when a context is destroyed
+ /// \param arg Argument to pass when calling the function
///
////////////////////////////////////////////////////////////
- static void ensureGlContext();
+ static void registerContextDestroyCallback(ContextDestroyCallback callback, void* arg);
////////////////////////////////////////////////////////////
/// \brief RAII helper class to temporarily lock an available context for use
@@ -81,9 +90,6 @@ protected:
///
////////////////////////////////////////////////////////////
~TransientContextLock();
-
- private:
- Context* m_context; ///< Temporary context, in case we needed to create one
};
};
diff --git a/include/SFML/Window/Joystick.hpp b/include/SFML/Window/Joystick.hpp
index dda7369..ab49c74 100644
--- a/include/SFML/Window/Joystick.hpp
+++ b/include/SFML/Window/Joystick.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/Keyboard.hpp b/include/SFML/Window/Keyboard.hpp
index b35c7a0..7c59c57 100644
--- a/include/SFML/Window/Keyboard.hpp
+++ b/include/SFML/Window/Keyboard.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -96,18 +96,18 @@ public:
Menu, ///< The Menu key
LBracket, ///< The [ key
RBracket, ///< The ] key
- SemiColon, ///< The ; key
+ Semicolon, ///< The ; key
Comma, ///< The , key
Period, ///< The . key
Quote, ///< The ' key
Slash, ///< The / key
- BackSlash, ///< The \ key
+ Backslash, ///< The \ key
Tilde, ///< The ~ key
Equal, ///< The = key
- Dash, ///< The - key
+ Hyphen, ///< The - key (hyphen)
Space, ///< The Space key
- Return, ///< The Return key
- BackSpace, ///< The Backspace key
+ Enter, ///< The Enter/Return keys
+ Backspace, ///< The Backspace key
Tab, ///< The Tabulation key
PageUp, ///< The Page up key
PageDown, ///< The Page down key
@@ -116,7 +116,7 @@ public:
Insert, ///< The Insert key
Delete, ///< The Delete key
Add, ///< The + key
- Subtract, ///< The - key
+ Subtract, ///< The - key (minus, usually from numpad)
Multiply, ///< The * key
Divide, ///< The / key
Left, ///< Left arrow
@@ -150,7 +150,15 @@ public:
F15, ///< The F15 key
Pause, ///< The Pause key
- KeyCount ///< Keep last -- the total number of keyboard keys
+ KeyCount, ///< Keep last -- the total number of keyboard keys
+
+ // Deprecated values:
+
+ Dash = Hyphen, ///< \deprecated Use Hyphen instead
+ BackSpace = Backspace, ///< \deprecated Use Backspace instead
+ BackSlash = Backslash, ///< \deprecated Use Backslash instead
+ SemiColon = Semicolon, ///< \deprecated Use Semicolon instead
+ Return = Enter ///< \deprecated Use Enter instead
};
////////////////////////////////////////////////////////////
diff --git a/include/SFML/Window/Mouse.hpp b/include/SFML/Window/Mouse.hpp
index 53d5281..0d1e470 100644
--- a/include/SFML/Window/Mouse.hpp
+++ b/include/SFML/Window/Mouse.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/Sensor.hpp b/include/SFML/Window/Sensor.hpp
index 9bef970..6915fa0 100644
--- a/include/SFML/Window/Sensor.hpp
+++ b/include/SFML/Window/Sensor.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/Touch.hpp b/include/SFML/Window/Touch.hpp
index 92c42df..1c2b3fe 100644
--- a/include/SFML/Window/Touch.hpp
+++ b/include/SFML/Window/Touch.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/VideoMode.hpp b/include/SFML/Window/VideoMode.hpp
index fee45ae..24797f6 100644
--- a/include/SFML/Window/VideoMode.hpp
+++ b/include/SFML/Window/VideoMode.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp
index 7135fdf..7ff81e2 100644
--- a/include/SFML/Window/Window.hpp
+++ b/include/SFML/Window/Window.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -28,16 +28,17 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
-#include <SFML/Window/Export.hpp>
#include <SFML/Window/ContextSettings.hpp>
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/Window/Export.hpp>
+#include <SFML/Window/GlResource.hpp>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/WindowHandle.hpp>
#include <SFML/Window/WindowStyle.hpp>
-#include <SFML/Window/GlResource.hpp>
#include <SFML/System/Clock.hpp>
-#include <SFML/System/Vector2.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/String.hpp>
+#include <SFML/System/Vector2.hpp>
namespace sf
@@ -362,6 +363,25 @@ public:
void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// Upon window creation, the arrow cursor is used by default.
+ ///
+ /// \warning The cursor must not be destroyed while in use by
+ /// the window.
+ ///
+ /// \warning Features related to Cursor are not supported on
+ /// iOS and Android.
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ /// \see sf::Cursor::loadFromSystem
+ /// \see sf::Cursor::loadFromPixels
+ ///
+ ////////////////////////////////////////////////////////////
+ void setMouseCursor(const Cursor& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// If key repeat is enabled, you will receive repeated
@@ -561,6 +581,14 @@ private:
/// structure which is passed as an optional argument when creating the
/// window.
///
+/// On dual-graphics systems consisting of a low-power integrated GPU
+/// and a powerful discrete GPU, the driver picks which GPU will run an
+/// SFML application. In order to inform the driver that an SFML application
+/// can benefit from being run on the more powerful discrete GPU,
+/// #SFML_DEFINE_DISCRETE_GPU_PREFERENCE can be placed in a source file
+/// that is compiled and linked into the final application. The macro
+/// should be placed outside of any scopes in the global namespace.
+///
/// Usage example:
/// \code
/// // Declare and create a new window
diff --git a/include/SFML/Window/WindowHandle.hpp b/include/SFML/Window/WindowHandle.hpp
index bfb4dc5..daad047 100644
--- a/include/SFML/Window/WindowHandle.hpp
+++ b/include/SFML/Window/WindowHandle.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -42,7 +42,7 @@ namespace sf
// Window handle is HWND (HWND__*) on Windows
typedef HWND__* WindowHandle;
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
// Window handle is Window (unsigned long) on Unix - X11
typedef unsigned long WindowHandle;
@@ -65,7 +65,7 @@ namespace sf
#elif defined(SFML_DOXYGEN)
// Define typedef symbol so that Doxygen can attach some documentation to it
- typedef "platform–specific" WindowHandle;
+ typedef "platform-specific" WindowHandle;
#endif
diff --git a/include/SFML/Window/WindowStyle.hpp b/include/SFML/Window/WindowStyle.hpp
index 8623d1f..53e2c9d 100644
--- a/include/SFML/Window/WindowStyle.hpp
+++ b/include/SFML/Window/WindowStyle.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/license.md b/license.md
new file mode 100644
index 0000000..0e6d7b1
--- /dev/null
+++ b/license.md
@@ -0,0 +1,20 @@
+# SFML
+
+SFML - Copyright (C) 2007-2018 Laurent Gomila - laurent@sfml-dev.org
+
+This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+ 1. 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 notice may not be removed or altered from any source distribution.
+
+## External libraries used by SFML
+
+ * _OpenAL-Soft_ is under the LGPL license
+ * _stb_image_ and _stb_image_write_ are public domain
+ * _freetype_ is under the FreeType license or the GPL license
+ * _libogg_ is under the BSD license
+ * _libvorbis_ is under the BSD license
+ * _libflac_ is under the BSD license
diff --git a/license.txt b/license.txt
deleted file mode 100644
index c988c6f..0000000
--- a/license.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-SFML
-----
-
-SFML - Copyright (C) 2007-2017 Laurent Gomila - laurent@sfml-dev.org
-
-This software is provided 'as-is', without any express or
-implied warranty. In no event will the authors be held
-liable for any damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute
-it freely, subject to the following restrictions:
-
-1. 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 notice may not be removed or altered from any
- source distribution.
-
-
-
-External libraries used by SFML
--------------------------------
-
-* OpenAL-Soft is under the LGPL license
-* libjpeg is public domain
-* stb_image and stb_image_write are public domain
-* freetype is under the FreeType license or the GPL license
-* libogg is under the BSD license
-* libvorbis is under the BSD license
-* libflac is under the BSD license
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..b6f9de0
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,39 @@
+[![SFML logo](https://www.sfml-dev.org/images/logo.png)](https://www.sfml-dev.org)
+
+# SFML — Simple and Fast Multimedia Library
+
+SFML is a simple, fast, cross-platform and object-oriented multimedia API. It provides access to windowing, graphics, audio and network. It is written in C++, and has bindings for various languages such as C, .Net, Ruby, Python.
+
+## Authors
+
+ - Laurent Gomila — main developer (laurent@sfml-dev.org)
+ - Marco Antognini — OS X developer (hiura@sfml-dev.org)
+ - Jonathan De Wachter — Android developer (dewachter.jonathan@gmail.com)
+ - Jan Haller (bromeon@sfml-dev.org)
+ - Stefan Schindler (tank@sfml-dev.org)
+ - Lukas Dürrenberger (eXpl0it3r@sfml-dev.org)
+ - binary1248 (binary1248@hotmail.com)
+ - Artur Moreira (artturmoreira@gmail.com)
+ - Mario Liebisch (mario@sfml-dev.org)
+ - And many other members of the SFML community
+
+## Download
+
+You can get the latest official release on [SFML's website](https://www.sfml-dev.org/download.php). You can also get the current development version from the [Git repository](https://github.com/SFML/SFML).
+
+## Install
+
+Follow the instructions of the [tutorials](https://www.sfml-dev.org/tutorials/), there is one for each platform/compiler that SFML supports.
+
+## Learn
+
+There are several places to learn SFML:
+
+ * The [official tutorials](https://www.sfml-dev.org/tutorials/)
+ * The [online API documentation](https://www.sfml-dev.org/documentation/)
+ * The [community wiki](https://github.com/SFML/SFML/wiki/)
+ * The [community forum](https://en.sfml-dev.org/forums/) ([French](https://fr.sfml-dev.org/forums/))
+
+## Contribute
+
+SFML is an open-source project, and it needs your help to go on growing and improving. If you want to get involved and suggest some additional features, file a bug report or submit a patch, please have a look at the [contribution guidelines](https://www.sfml-dev.org/contribute.php).
diff --git a/readme.txt b/readme.txt
deleted file mode 100644
index 28beb60..0000000
--- a/readme.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-SFML - Simple and Fast Multimedia Library
-=========================================
-
-SFML is a simple, fast, cross-platform and object-oriented multimedia API. It provides access to windowing, graphics, audio and network.
-It is written in C++, and has bindings for various languages such as C, .Net, Ruby, Python.
-
-Authors
--------
-
-Laurent Gomila - main developer (laurent@sfml-dev.org)
-Marco Antognini - OS X developer (hiura@sfml-dev.org)
-Jonathan De Wachter - Android developer (dewachter.jonathan@gmail.com)
-Jan Haller (bromeon@sfml-dev.org)
-Stefan Schindler (tank@sfml-dev.org)
-Lukas Dürrenberger (eXpl0it3r@sfml-dev.org)
-binary1248 (binary1248@hotmail.com)
-Artur Moreira (artturmoreira@gmail.com)
-Mario Liebisch (mario@sfml-dev.org)
-
-Download
---------
-
-You can get the latest official release on SFML website (http://www.sfml-dev.org/download.php).
-You can also get the current development version from the git repository (https://github.com/SFML/SFML).
-
-Install
--------
-
-Follow the instructions of the tutorials (http://www.sfml-dev.org/tutorials/), there is one for each platform/compiler that SFML supports.
-
-Learn
------
-
-There are several places to learn SFML:
-* The official tutorials (http://www.sfml-dev.org/tutorials/)
-* The online API documentation (http://www.sfml-dev.org/documentation/)
-* The community wiki (https://github.com/SFML/SFML/wiki/)
-* The community forum (http://en.sfml-dev.org/forums/) (or http://fr.sfml-dev.org/forums/ for French people)
-
-Contribute
-----------
-
-SFML is an open-source project, and it needs your help to go on growing and improving.
-If you want to get involved and suggest some additional features, file a bug report or submit a patch, please have a look at the contribution guidelines (http://www.sfml-dev.org/contribute.php).
diff --git a/src/SFML/Android.mk b/src/SFML/Android.mk
index f4f586d..2c3a626 100644
--- a/src/SFML/Android.mk
+++ b/src/SFML/Android.mk
@@ -179,5 +179,5 @@ ifdef prebuilt
include $(PREBUILT_SHARED_LIBRARY)
endif
-$(call import-module,sfml/extlibs)
+$(call import-module,third_party/sfml/extlibs)
diff --git a/src/SFML/Audio/ALCheck.cpp b/src/SFML/Audio/ALCheck.cpp
index e3b7bb6..b6f1e2a 100644
--- a/src/SFML/Audio/ALCheck.cpp
+++ b/src/SFML/Audio/ALCheck.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/ALCheck.hpp b/src/SFML/Audio/ALCheck.hpp
index 85f4e72..c67d117 100644
--- a/src/SFML/Audio/ALCheck.hpp
+++ b/src/SFML/Audio/ALCheck.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -29,14 +29,9 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
-#ifdef SFML_SYSTEM_IOS
- #include <OpenAl/al.h>
- #include <OpenAl/alc.h>
-#else
- #include <al.h>
- #include <alc.h>
-#endif
+#include <al.h>
+#include <alc.h>
namespace sf
{
diff --git a/src/SFML/Audio/AlResource.cpp b/src/SFML/Audio/AlResource.cpp
index df50be0..9be2e34 100644
--- a/src/SFML/Audio/AlResource.cpp
+++ b/src/SFML/Audio/AlResource.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/AudioDevice.cpp b/src/SFML/Audio/AudioDevice.cpp
index 4a2c55f..a9472f0 100644
--- a/src/SFML/Audio/AudioDevice.cpp
+++ b/src/SFML/Audio/AudioDevice.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/AudioDevice.hpp b/src/SFML/Audio/AudioDevice.hpp
index 9d3f6e8..f5007ed 100644
--- a/src/SFML/Audio/AudioDevice.hpp
+++ b/src/SFML/Audio/AudioDevice.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/CMakeLists.txt b/src/SFML/Audio/CMakeLists.txt
index e375057..420e13b 100644
--- a/src/SFML/Audio/CMakeLists.txt
+++ b/src/SFML/Audio/CMakeLists.txt
@@ -66,39 +66,25 @@ elseif(SFML_OS_ANDROID)
endif()
# find external libraries
-if(NOT SFML_OS_ANDROID)
- if(NOT SFML_OS_IOS)
- find_package(OpenAL REQUIRED)
- endif()
- find_package(Vorbis REQUIRED)
- find_package(FLAC REQUIRED)
-else()
- find_host_package(OpenAL REQUIRED)
- find_host_package(Vorbis REQUIRED)
- find_host_package(FLAC REQUIRED)
-endif()
+sfml_find_package(OpenAL INCLUDE "OPENAL_INCLUDE_DIR" LINK "OPENAL_LIBRARY")
+sfml_find_package(Vorbis INCLUDE "VORBIS_INCLUDE_DIRS" LINK "VORBIS_LIBRARIES")
+sfml_find_package(FLAC INCLUDE "FLAC_INCLUDE_DIR" LINK "FLAC_LIBRARY")
-if(NOT SFML_OS_IOS)
- include_directories(${OPENAL_INCLUDE_DIR})
-endif()
-include_directories(${VORBIS_INCLUDE_DIRS})
-include_directories(${FLAC_INCLUDE_DIR})
-add_definitions(-DOV_EXCLUDE_STATIC_CALLBACKS) # avoids warnings in vorbisfile.h
-add_definitions(-DFLAC__NO_DLL)
+# avoids warnings in vorbisfile.h
+target_compile_definitions(Vorbis INTERFACE "OV_EXCLUDE_STATIC_CALLBACKS")
+target_compile_definitions(FLAC INTERFACE "FLAC__NO_DLL")
+
+# define the sfml-audio target
+sfml_add_library(sfml-audio
+ SOURCES ${SRC} ${CODECS_SRC})
+
+# setup dependencies
+target_link_libraries(sfml-audio PRIVATE OpenAL)
-# build the list of external libraries to link
-if(SFML_OS_IOS)
- list(APPEND AUDIO_EXT_LIBS "-framework OpenAL")
-else()
- list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY})
-endif()
if(SFML_OS_ANDROID)
- list(APPEND AUDIO_EXT_LIBS android OpenSLES)
+ target_link_libraries(sfml-audio PRIVATE android OpenSLES)
endif()
-list(APPEND AUDIO_EXT_LIBS ${VORBIS_LIBRARIES} ${FLAC_LIBRARY})
-# define the sfml-audio target
-sfml_add_library(sfml-audio
- SOURCES ${SRC} ${CODECS_SRC}
- DEPENDS sfml-system
- EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
+target_link_libraries(sfml-audio
+ PUBLIC sfml-system
+ PRIVATE Vorbis FLAC)
diff --git a/src/SFML/Audio/InputSoundFile.cpp b/src/SFML/Audio/InputSoundFile.cpp
index cdc46a5..9cc781f 100644
--- a/src/SFML/Audio/InputSoundFile.cpp
+++ b/src/SFML/Audio/InputSoundFile.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -41,6 +41,7 @@ InputSoundFile::InputSoundFile() :
m_reader (NULL),
m_stream (NULL),
m_streamOwned (false),
+m_sampleOffset (0),
m_sampleCount (0),
m_channelCount(0),
m_sampleRate (0)
@@ -195,15 +196,42 @@ unsigned int InputSoundFile::getSampleRate() const
////////////////////////////////////////////////////////////
Time InputSoundFile::getDuration() const
{
+ // Make sure we don't divide by 0
+ if (m_channelCount == 0 || m_sampleRate == 0)
+ return Time::Zero;
+
return seconds(static_cast<float>(m_sampleCount) / m_channelCount / m_sampleRate);
}
////////////////////////////////////////////////////////////
+Time InputSoundFile::getTimeOffset() const
+{
+ // Make sure we don't divide by 0
+ if (m_channelCount == 0 || m_sampleRate == 0)
+ return Time::Zero;
+
+ return seconds(static_cast<float>(m_sampleOffset) / m_channelCount / m_sampleRate);
+}
+
+
+////////////////////////////////////////////////////////////
+Uint64 InputSoundFile::getSampleOffset() const
+{
+ return m_sampleOffset;
+}
+
+
+////////////////////////////////////////////////////////////
void InputSoundFile::seek(Uint64 sampleOffset)
{
if (m_reader)
- m_reader->seek(sampleOffset);
+ {
+ // The reader handles an overrun gracefully, but we
+ // pre-check to keep our known position consistent
+ m_sampleOffset = std::min(sampleOffset, m_sampleCount);
+ m_reader->seek(m_sampleOffset);
+ }
}
@@ -217,10 +245,11 @@ void InputSoundFile::seek(Time timeOffset)
////////////////////////////////////////////////////////////
Uint64 InputSoundFile::read(Int16* samples, Uint64 maxCount)
{
+ Uint64 readSamples = 0;
if (m_reader && samples && maxCount)
- return m_reader->read(samples, maxCount);
- else
- return 0;
+ readSamples = m_reader->read(samples, maxCount);
+ m_sampleOffset += readSamples;
+ return readSamples;
}
@@ -238,6 +267,7 @@ void InputSoundFile::close()
m_streamOwned = false;
}
m_stream = NULL;
+ m_sampleOffset = 0;
// Reset the sound file attributes
m_sampleCount = 0;
diff --git a/src/SFML/Audio/Listener.cpp b/src/SFML/Audio/Listener.cpp
index 23e0aaf..dc348f9 100644
--- a/src/SFML/Audio/Listener.cpp
+++ b/src/SFML/Audio/Listener.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp
index 7ee5208..141d690 100644
--- a/src/SFML/Audio/Music.cpp
+++ b/src/SFML/Audio/Music.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -36,8 +36,8 @@ namespace sf
{
////////////////////////////////////////////////////////////
Music::Music() :
-m_file (),
-m_duration()
+m_file (),
+m_loopSpan (0, 0)
{
}
@@ -105,7 +105,73 @@ bool Music::openFromStream(InputStream& stream)
////////////////////////////////////////////////////////////
Time Music::getDuration() const
{
- return m_duration;
+ return m_file.getDuration();
+}
+
+
+////////////////////////////////////////////////////////////
+Music::TimeSpan Music::getLoopPoints() const
+{
+ return TimeSpan(samplesToTime(m_loopSpan.offset), samplesToTime(m_loopSpan.length));
+}
+
+
+////////////////////////////////////////////////////////////
+void Music::setLoopPoints(TimeSpan timePoints)
+{
+ Span<Uint64> samplePoints(timeToSamples(timePoints.offset), timeToSamples(timePoints.length));
+
+ // Check our state. This averts a divide-by-zero. GetChannelCount() is cheap enough to use often
+ if (getChannelCount() == 0 || m_file.getSampleCount() == 0)
+ {
+ sf::err() << "Music is not in a valid state to assign Loop Points." << std::endl;
+ return;
+ }
+
+ // Round up to the next even sample if needed
+ samplePoints.offset += (getChannelCount() - 1);
+ samplePoints.offset -= (samplePoints.offset % getChannelCount());
+ samplePoints.length += (getChannelCount() - 1);
+ samplePoints.length -= (samplePoints.length % getChannelCount());
+
+ // Validate
+ if (samplePoints.offset >= m_file.getSampleCount())
+ {
+ sf::err() << "LoopPoints offset val must be in range [0, Duration)." << std::endl;
+ return;
+ }
+ if (samplePoints.length == 0)
+ {
+ sf::err() << "LoopPoints length val must be nonzero." << std::endl;
+ return;
+ }
+
+ // Clamp End Point
+ samplePoints.length = std::min(samplePoints.length, m_file.getSampleCount() - samplePoints.offset);
+
+ // If this change has no effect, we can return without touching anything
+ if (samplePoints.offset == m_loopSpan.offset && samplePoints.length == m_loopSpan.length)
+ return;
+
+ // When we apply this change, we need to "reset" this instance and its buffer
+
+ // Get old playing status and position
+ Status oldStatus = getStatus();
+ Time oldPos = getPlayingOffset();
+
+ // Unload
+ stop();
+
+ // Set
+ m_loopSpan = samplePoints;
+
+ // Restore
+ if (oldPos != Time::Zero)
+ setPlayingOffset(oldPos);
+
+ // Resume
+ if (oldStatus == Playing)
+ play();
}
@@ -114,12 +180,23 @@ bool Music::onGetData(SoundStream::Chunk& data)
{
Lock lock(m_mutex);
+ std::size_t toFill = m_samples.size();
+ Uint64 currentOffset = m_file.getSampleOffset();
+ Uint64 loopEnd = m_loopSpan.offset + m_loopSpan.length;
+
+ // If the loop end is enabled and imminent, request less data.
+ // This will trip an "onLoop()" call from the underlying SoundStream,
+ // and we can then take action.
+ if (getLoop() && (m_loopSpan.length != 0) && (currentOffset <= loopEnd) && (currentOffset + toFill > loopEnd))
+ toFill = static_cast<std::size_t>(loopEnd - currentOffset);
+
// Fill the chunk parameters
- data.samples = &m_samples[0];
- data.sampleCount = static_cast<std::size_t>(m_file.read(&m_samples[0], m_samples.size()));
+ data.samples = &m_samples[0];
+ data.sampleCount = static_cast<std::size_t>(m_file.read(&m_samples[0], toFill));
+ currentOffset += data.sampleCount;
- // Check if we have reached the end of the audio file
- return data.sampleCount == m_samples.size();
+ // Check if we have stopped obtaining samples or reached either the EOF or the loop end point
+ return (data.sampleCount != 0) && (currentOffset < m_file.getSampleCount()) && !(currentOffset == loopEnd && m_loopSpan.length != 0);
}
@@ -127,16 +204,39 @@ bool Music::onGetData(SoundStream::Chunk& data)
void Music::onSeek(Time timeOffset)
{
Lock lock(m_mutex);
-
m_file.seek(timeOffset);
}
////////////////////////////////////////////////////////////
+Int64 Music::onLoop()
+{
+ // Called by underlying SoundStream so we can determine where to loop.
+ Lock lock(m_mutex);
+ Uint64 currentOffset = m_file.getSampleOffset();
+ if (getLoop() && (m_loopSpan.length != 0) && (currentOffset == m_loopSpan.offset + m_loopSpan.length))
+ {
+ // Looping is enabled, and either we're at the loop end, or we're at the EOF
+ // when it's equivalent to the loop end (loop end takes priority). Send us to loop begin
+ m_file.seek(m_loopSpan.offset);
+ return m_file.getSampleOffset();
+ }
+ else if (getLoop() && (currentOffset >= m_file.getSampleCount()))
+ {
+ // If we're at the EOF, reset to 0
+ m_file.seek(0);
+ return 0;
+ }
+ return NoLoop;
+}
+
+
+////////////////////////////////////////////////////////////
void Music::initialize()
{
- // Compute the music duration
- m_duration = m_file.getDuration();
+ // Compute the music positions
+ m_loopSpan.offset = 0;
+ m_loopSpan.length = m_file.getSampleCount();
// Resize the internal buffer so that it can contain 1 second of audio samples
m_samples.resize(m_file.getSampleRate() * m_file.getChannelCount());
@@ -145,4 +245,27 @@ void Music::initialize()
SoundStream::initialize(m_file.getChannelCount(), m_file.getSampleRate());
}
+////////////////////////////////////////////////////////////
+Uint64 Music::timeToSamples(Time position) const
+{
+ // Always ROUND, no unchecked truncation, hence the addition in the numerator.
+ // This avoids most precision errors arising from "samples => Time => samples" conversions
+ // Original rounding calculation is ((Micros * Freq * Channels) / 1000000) + 0.5
+ // We refactor it to keep Int64 as the data type throughout the whole operation.
+ return ((position.asMicroseconds() * getSampleRate() * getChannelCount()) + 500000) / 1000000;
+}
+
+
+////////////////////////////////////////////////////////////
+Time Music::samplesToTime(Uint64 samples) const
+{
+ Time position = Time::Zero;
+
+ // Make sure we don't divide by 0
+ if (getSampleRate() != 0 && getChannelCount() != 0)
+ position = microseconds((samples * 1000000) / (getChannelCount() * getSampleRate()));
+
+ return position;
+}
+
} // namespace sf
diff --git a/src/SFML/Audio/OutputSoundFile.cpp b/src/SFML/Audio/OutputSoundFile.cpp
index 870e622..16e41d3 100644
--- a/src/SFML/Audio/OutputSoundFile.cpp
+++ b/src/SFML/Audio/OutputSoundFile.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/Sound.cpp b/src/SFML/Audio/Sound.cpp
index 8ebaa03..b7a0b13 100644
--- a/src/SFML/Audio/Sound.cpp
+++ b/src/SFML/Audio/Sound.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp
index c984204..edcd455 100644
--- a/src/SFML/Audio/SoundBuffer.cpp
+++ b/src/SFML/Audio/SoundBuffer.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundBufferRecorder.cpp b/src/SFML/Audio/SoundBufferRecorder.cpp
index 105b45b..3c70a65 100644
--- a/src/SFML/Audio/SoundBufferRecorder.cpp
+++ b/src/SFML/Audio/SoundBufferRecorder.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileFactory.cpp b/src/SFML/Audio/SoundFileFactory.cpp
index 10b1c1e..8138319 100644
--- a/src/SFML/Audio/SoundFileFactory.cpp
+++ b/src/SFML/Audio/SoundFileFactory.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileReaderFlac.cpp b/src/SFML/Audio/SoundFileReaderFlac.cpp
index 80bde57..f42a132 100644
--- a/src/SFML/Audio/SoundFileReaderFlac.cpp
+++ b/src/SFML/Audio/SoundFileReaderFlac.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -107,10 +107,6 @@ namespace
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
- // If there's no output buffer, it means that we are seeking
- if (!data->buffer)
- return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-
// Reserve memory if we're going to use the leftovers buffer
unsigned int frameSamples = frame->header.blocksize * frame->header.channels;
if (data->remaining < frameSamples)
@@ -142,15 +138,16 @@ namespace
break;
}
- if (data->remaining > 0)
+ if (data->buffer && data->remaining > 0)
{
- // There's room in the output buffer, copy the sample there
+ // If there's room in the output buffer, copy the sample there
*data->buffer++ = sample;
data->remaining--;
}
else
{
- // We have decoded all the requested samples, put the sample in a temporary buffer until next call
+ // We are either seeking (null buffer) or have decoded all the requested samples during a
+ // normal read (0 remaining), so we put the sample in a temporary buffer until next call
data->leftovers.push_back(sample);
}
}
@@ -210,8 +207,7 @@ bool SoundFileReaderFlac::check(InputStream& stream)
////////////////////////////////////////////////////////////
SoundFileReaderFlac::SoundFileReaderFlac() :
m_decoder(NULL),
-m_clientData(),
-m_channelCount(0)
+m_clientData()
{
}
@@ -249,9 +245,6 @@ bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
// Retrieve the sound properties
info = m_clientData.info; // was filled in the "metadata" callback
- // We must keep the channel count for the seek function
- m_channelCount = info.channelCount;
-
return true;
}
@@ -267,7 +260,21 @@ void SoundFileReaderFlac::seek(Uint64 sampleOffset)
m_clientData.leftovers.clear();
// FLAC decoder expects absolute sample offset, so we take the channel count out
- FLAC__stream_decoder_seek_absolute(m_decoder, sampleOffset / m_channelCount);
+ if (sampleOffset < m_clientData.info.sampleCount)
+ {
+ // The "write" callback will populate the leftovers buffer with the first batch of samples from the
+ // seek destination, and since we want that data in this typical case, we don't re-clear it afterward
+ FLAC__stream_decoder_seek_absolute(m_decoder, sampleOffset / m_clientData.info.channelCount);
+ }
+ else
+ {
+ // FLAC decoder can't skip straight to EOF, so we short-seek by one sample and skip the rest
+ FLAC__stream_decoder_seek_absolute(m_decoder, (m_clientData.info.sampleCount / m_clientData.info.channelCount) - 1);
+ FLAC__stream_decoder_skip_single_frame(m_decoder);
+
+ // This was re-populated during the seek, but we're skipping everything in this, so we need it emptied
+ m_clientData.leftovers.clear();
+ }
}
@@ -277,14 +284,14 @@ Uint64 SoundFileReaderFlac::read(Int16* samples, Uint64 maxCount)
assert(m_decoder);
// If there are leftovers from previous call, use it first
- Uint64 left = m_clientData.leftovers.size();
+ std::size_t left = m_clientData.leftovers.size();
if (left > 0)
{
if (left > maxCount)
{
// There are more leftovers than needed
- std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.end(), samples);
- std::vector<Int16> leftovers(m_clientData.leftovers.begin() + maxCount, m_clientData.leftovers.end());
+ std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.begin() + static_cast<std::size_t>(maxCount), samples);
+ std::vector<Int16> leftovers(m_clientData.leftovers.begin() + static_cast<std::size_t>(maxCount), m_clientData.leftovers.end());
m_clientData.leftovers.swap(leftovers);
return maxCount;
}
diff --git a/src/SFML/Audio/SoundFileReaderFlac.hpp b/src/SFML/Audio/SoundFileReaderFlac.hpp
index 9937564..6cb0b86 100644
--- a/src/SFML/Audio/SoundFileReaderFlac.hpp
+++ b/src/SFML/Audio/SoundFileReaderFlac.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -83,8 +83,9 @@ public:
/// \brief Change the current read position to the given sample offset
///
/// The sample offset takes the channels into account.
- /// Offsets can be calculated like this:
- /// `sampleNumber * sampleRate * channelCount`
+ /// If you have a time offset instead, you can easily find
+ /// the corresponding sample offset with the following formula:
+ /// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
@@ -131,9 +132,8 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- FLAC__StreamDecoder* m_decoder; ///< FLAC decoder
- ClientData m_clientData; ///< Structure passed to the decoder callbacks
- unsigned int m_channelCount; ///< number of channels of the sound file
+ FLAC__StreamDecoder* m_decoder; ///< FLAC decoder
+ ClientData m_clientData; ///< Structure passed to the decoder callbacks
};
} // namespace priv
diff --git a/src/SFML/Audio/SoundFileReaderOgg.cpp b/src/SFML/Audio/SoundFileReaderOgg.cpp
index df46193..183e3b2 100644
--- a/src/SFML/Audio/SoundFileReaderOgg.cpp
+++ b/src/SFML/Audio/SoundFileReaderOgg.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileReaderOgg.hpp b/src/SFML/Audio/SoundFileReaderOgg.hpp
index b1bf252..0e84e8f 100644
--- a/src/SFML/Audio/SoundFileReaderOgg.hpp
+++ b/src/SFML/Audio/SoundFileReaderOgg.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -83,8 +83,9 @@ public:
/// \brief Change the current read position to the given sample offset
///
/// The sample offset takes the channels into account.
- /// Offsets can be calculated like this:
- /// `sampleNumber * sampleRate * channelCount`
+ /// If you have a time offset instead, you can easily find
+ /// the corresponding sample offset with the following formula:
+ /// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
diff --git a/src/SFML/Audio/SoundFileReaderWav.cpp b/src/SFML/Audio/SoundFileReaderWav.cpp
index 6f4a777..dc1dc52 100644
--- a/src/SFML/Audio/SoundFileReaderWav.cpp
+++ b/src/SFML/Audio/SoundFileReaderWav.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,7 @@
#include <algorithm>
#include <cctype>
#include <cassert>
+#include <cstring>
namespace
@@ -88,6 +89,14 @@ namespace
}
const sf::Uint64 mainChunkSize = 12;
+
+ const sf::Uint16 waveFormatPcm = 1;
+
+ const sf::Uint16 waveFormatExtensible= 65534;
+
+ const char* waveSubformatPcm =
+ "\x01\x00\x00\x00\x00\x00\x10\x00"
+ "\x80\x00\x00\xAA\x00\x38\x9B\x71";
}
namespace sf
@@ -146,7 +155,7 @@ Uint64 SoundFileReaderWav::read(Int16* samples, Uint64 maxCount)
assert(m_stream);
Uint64 count = 0;
- while ((count < maxCount) && (m_stream->tell() < m_dataEnd))
+ while ((count < maxCount) && (static_cast<Uint64>(m_stream->tell()) < m_dataEnd))
{
switch (m_bytesPerSample)
{
@@ -226,6 +235,9 @@ bool SoundFileReaderWav::parseHeader(Info& info)
Uint32 subChunkSize = 0;
if (!decode(*m_stream, subChunkSize))
return false;
+ Int64 subChunkStart = m_stream->tell();
+ if (subChunkStart == -1)
+ return false;
// Check which chunk it is
if ((subChunkId[0] == 'f') && (subChunkId[1] == 'm') && (subChunkId[2] == 't') && (subChunkId[3] == ' '))
@@ -236,7 +248,7 @@ bool SoundFileReaderWav::parseHeader(Info& info)
Uint16 format = 0;
if (!decode(*m_stream, format))
return false;
- if (format != 1) // PCM
+ if ((format != waveFormatPcm) && (format != waveFormatExtensible))
return false;
// Channel count
@@ -272,12 +284,45 @@ bool SoundFileReaderWav::parseHeader(Info& info)
}
m_bytesPerSample = bitsPerSample / 8;
- // Skip potential extra information (should not exist for PCM)
- if (subChunkSize > 16)
+ if (format == waveFormatExtensible)
{
- if (m_stream->seek(m_stream->tell() + subChunkSize - 16) == -1)
+ // Extension size
+ Uint16 extensionSize = 0;
+ if (!decode(*m_stream, extensionSize))
+ return false;
+
+ // Valid bits per sample
+ Uint16 validBitsPerSample = 0;
+ if (!decode(*m_stream, validBitsPerSample))
+ return false;
+
+ // Channel mask
+ Uint32 channelMask = 0;
+ if (!decode(*m_stream, channelMask))
return false;
+
+ // Subformat
+ char subformat[16];
+ if (m_stream->read(subformat, sizeof(subformat)) != sizeof(subformat))
+ return false;
+
+ if (std::memcmp(subformat, waveSubformatPcm, sizeof(subformat)) != 0)
+ {
+ err() << "Unsupported format: extensible format with non-PCM subformat" << std::endl;
+ return false;
+ }
+
+ if (validBitsPerSample != bitsPerSample)
+ {
+ err() << "Unsupported format: sample size (" << validBitsPerSample << " bits) and "
+ "sample container size (" << bitsPerSample << " bits) differ" << std::endl;
+ return false;
+ }
}
+
+ // Skip potential extra information
+ if (m_stream->seek(subChunkStart + subChunkSize) == -1)
+ return false;
}
else if ((subChunkId[0] == 'd') && (subChunkId[1] == 'a') && (subChunkId[2] == 't') && (subChunkId[3] == 'a'))
{
@@ -287,7 +332,7 @@ bool SoundFileReaderWav::parseHeader(Info& info)
info.sampleCount = subChunkSize / m_bytesPerSample;
// Store the start and end position of samples in the file
- m_dataStart = m_stream->tell();
+ m_dataStart = subChunkStart;
m_dataEnd = m_dataStart + info.sampleCount * m_bytesPerSample;
dataChunkFound = true;
diff --git a/src/SFML/Audio/SoundFileReaderWav.hpp b/src/SFML/Audio/SoundFileReaderWav.hpp
index 904408b..65adb8d 100644
--- a/src/SFML/Audio/SoundFileReaderWav.hpp
+++ b/src/SFML/Audio/SoundFileReaderWav.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -75,8 +75,9 @@ public:
/// \brief Change the current read position to the given sample offset
///
/// The sample offset takes the channels into account.
- /// Offsets can be calculated like this:
- /// `sampleNumber * sampleRate * channelCount`
+ /// If you have a time offset instead, you can easily find
+ /// the corresponding sample offset with the following formula:
+ /// `timeInSeconds * sampleRate * channelCount`
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
diff --git a/src/SFML/Audio/SoundFileWriterFlac.cpp b/src/SFML/Audio/SoundFileWriterFlac.cpp
index b12088b..045d086 100644
--- a/src/SFML/Audio/SoundFileWriterFlac.cpp
+++ b/src/SFML/Audio/SoundFileWriterFlac.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileWriterFlac.hpp b/src/SFML/Audio/SoundFileWriterFlac.hpp
index 39f50db..b6382e0 100644
--- a/src/SFML/Audio/SoundFileWriterFlac.hpp
+++ b/src/SFML/Audio/SoundFileWriterFlac.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileWriterOgg.cpp b/src/SFML/Audio/SoundFileWriterOgg.cpp
index c661b74..56e2ac7 100644
--- a/src/SFML/Audio/SoundFileWriterOgg.cpp
+++ b/src/SFML/Audio/SoundFileWriterOgg.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileWriterOgg.hpp b/src/SFML/Audio/SoundFileWriterOgg.hpp
index 868464a..4b4d19b 100644
--- a/src/SFML/Audio/SoundFileWriterOgg.hpp
+++ b/src/SFML/Audio/SoundFileWriterOgg.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundFileWriterWav.cpp b/src/SFML/Audio/SoundFileWriterWav.cpp
index 1b48fe5..153e148 100644
--- a/src/SFML/Audio/SoundFileWriterWav.cpp
+++ b/src/SFML/Audio/SoundFileWriterWav.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -86,9 +86,7 @@ bool SoundFileWriterWav::check(const std::string& filename)
////////////////////////////////////////////////////////////
SoundFileWriterWav::SoundFileWriterWav() :
-m_file (),
-m_sampleCount (0),
-m_channelCount(0)
+m_file()
{
}
@@ -118,9 +116,6 @@ bool SoundFileWriterWav::open(const std::string& filename, unsigned int sampleRa
return false;
}
- // Save the channel count
- m_channelCount = channelCount;
-
return true;
}
@@ -130,8 +125,6 @@ void SoundFileWriterWav::write(const Int16* samples, Uint64 count)
{
assert(m_file.good());
- m_sampleCount += count;
-
while (count--)
encode(m_file, *samples++);
}
@@ -191,8 +184,9 @@ void SoundFileWriterWav::close()
m_file.flush();
// Update the main chunk size and data sub-chunk size
- Uint32 dataChunkSize = static_cast<Uint32>(m_sampleCount * m_channelCount * 2);
- Uint32 mainChunkSize = dataChunkSize + 36;
+ Uint32 fileSize = static_cast<Uint32>(m_file.tellp());
+ Uint32 mainChunkSize = fileSize - 8; // 8 bytes RIFF header
+ Uint32 dataChunkSize = fileSize - 44; // 44 bytes RIFF + WAVE headers
m_file.seekp(4);
encode(m_file, mainChunkSize);
m_file.seekp(40);
diff --git a/src/SFML/Audio/SoundFileWriterWav.hpp b/src/SFML/Audio/SoundFileWriterWav.hpp
index b37a970..d8dcc17 100644
--- a/src/SFML/Audio/SoundFileWriterWav.hpp
+++ b/src/SFML/Audio/SoundFileWriterWav.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -113,8 +113,6 @@ private:
// Member data
////////////////////////////////////////////////////////////
std::ofstream m_file; ///< File stream to write to
- Uint64 m_sampleCount; ///< Total number of samples written to the file
- unsigned int m_channelCount; ///< Number of channels of the sound
};
} // namespace priv
diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp
index 7105fbd..4281b98 100644
--- a/src/SFML/Audio/SoundRecorder.cpp
+++ b/src/SFML/Audio/SoundRecorder.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -188,7 +188,7 @@ bool SoundRecorder::setDevice(const std::string& name)
ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
// Open the requested capture device for capturing 16 bits samples
- captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, format, m_sampleRate);
+ captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), m_sampleRate, format, m_sampleRate);
if (!captureDevice)
{
// Notify derived class
diff --git a/src/SFML/Audio/SoundSource.cpp b/src/SFML/Audio/SoundSource.cpp
index b2b4059..785f9cc 100644
--- a/src/SFML/Audio/SoundSource.cpp
+++ b/src/SFML/Audio/SoundSource.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Audio/SoundStream.cpp b/src/SFML/Audio/SoundStream.cpp
index 9e147a5..0e40548 100644
--- a/src/SFML/Audio/SoundStream.cpp
+++ b/src/SFML/Audio/SoundStream.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -51,7 +51,7 @@ m_sampleRate (0),
m_format (0),
m_loop (false),
m_samplesProcessed(0),
-m_endBuffers ()
+m_bufferSeeks ()
{
}
@@ -77,7 +77,9 @@ SoundStream::~SoundStream()
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
{
m_channelCount = channelCount;
- m_sampleRate = sampleRate;
+ m_sampleRate = sampleRate;
+ m_samplesProcessed = 0;
+ m_isStreaming = false;
// Deduce the format from the number of channels
m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
@@ -127,11 +129,7 @@ void SoundStream::play()
stop();
}
- // Move to the beginning
- onSeek(Time::Zero);
-
// Start updating the stream in a separate thread to avoid blocking the application
- m_samplesProcessed = 0;
m_isStreaming = true;
m_threadStartState = Playing;
m_thread.launch();
@@ -169,9 +167,6 @@ void SoundStream::stop()
// Move to the beginning
onSeek(Time::Zero);
-
- // Reset the playing position
- m_samplesProcessed = 0;
}
@@ -263,6 +258,14 @@ bool SoundStream::getLoop() const
////////////////////////////////////////////////////////////
+Int64 SoundStream::onLoop()
+{
+ onSeek(Time::Zero);
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////
void SoundStream::streamData()
{
bool requestStop = false;
@@ -281,7 +284,7 @@ void SoundStream::streamData()
// Create the buffers
alCheck(alGenBuffers(BufferCount, m_buffers));
for (int i = 0; i < BufferCount; ++i)
- m_endBuffers[i] = false;
+ m_bufferSeeks[i] = NoLoop;
// Fill the queue
requestStop = fillQueue();
@@ -341,11 +344,11 @@ void SoundStream::streamData()
}
// Retrieve its size and add it to the samples count
- if (m_endBuffers[bufferNum])
+ if (m_bufferSeeks[bufferNum] != NoLoop)
{
- // This was the last buffer: reset the sample count
- m_samplesProcessed = 0;
- m_endBuffers[bufferNum] = false;
+ // This was the last buffer before EOF or Loop End: reset the sample count
+ m_samplesProcessed = m_bufferSeeks[bufferNum];
+ m_bufferSeeks[bufferNum] = NoLoop;
}
else
{
@@ -390,6 +393,9 @@ void SoundStream::streamData()
// Dequeue any buffer left in the queue
clearQueue();
+ // Reset the playing position
+ m_samplesProcessed = 0;
+
// Delete the buffers
alCheck(alSourcei(m_source, AL_BUFFER, 0));
alCheck(alDeleteBuffers(BufferCount, m_buffers));
@@ -397,34 +403,41 @@ void SoundStream::streamData()
////////////////////////////////////////////////////////////
-bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
+bool SoundStream::fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop)
{
bool requestStop = false;
- // Acquire audio data
+ // Acquire audio data, also address EOF and error cases if they occur
Chunk data = {NULL, 0};
- if (!onGetData(data))
+ for (Uint32 retryCount = 0; !onGetData(data) && (retryCount < BufferRetries); ++retryCount)
{
- // Mark the buffer as the last one (so that we know when to reset the playing position)
- m_endBuffers[bufferNum] = true;
-
// Check if the stream must loop or stop
- if (m_loop)
+ if (!m_loop)
{
- // Return to the beginning of the stream source
- onSeek(Time::Zero);
-
- // If we previously had no data, try to fill the buffer once again
- if (!data.samples || (data.sampleCount == 0))
- {
- return fillAndPushBuffer(bufferNum);
- }
+ // Not looping: Mark this buffer as ending with 0 and request stop
+ if (data.samples != NULL && data.sampleCount != 0)
+ m_bufferSeeks[bufferNum] = 0;
+ requestStop = true;
+ break;
}
- else
+
+ // Return to the beginning or loop-start of the stream source using onLoop(), and store the result in the buffer seek array
+ // This marks the buffer as the "last" one (so that we know where to reset the playing position)
+ m_bufferSeeks[bufferNum] = onLoop();
+
+ // If we got data, break and process it, else try to fill the buffer once again
+ if (data.samples != NULL && data.sampleCount != 0)
+ break;
+
+ // If immediateLoop is specified, we have to immediately adjust the sample count
+ if (immediateLoop && (m_bufferSeeks[bufferNum] != NoLoop))
{
- // Not looping: request stop
- requestStop = true;
+ // We just tried to begin preloading at EOF or Loop End: reset the sample count
+ m_samplesProcessed = m_bufferSeeks[bufferNum];
+ m_bufferSeeks[bufferNum] = NoLoop;
}
+
+ // We're a looping sound that got no data, so we retry onGetData()
}
// Fill the buffer if some data was returned
@@ -439,6 +452,11 @@ bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
// Push it into the sound queue
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
}
+ else
+ {
+ // If we get here, we most likely ran out of retries
+ requestStop = true;
+ }
return requestStop;
}
@@ -451,7 +469,9 @@ bool SoundStream::fillQueue()
bool requestStop = false;
for (int i = 0; (i < BufferCount) && !requestStop; ++i)
{
- if (fillAndPushBuffer(i))
+ // Since no sound has been loaded yet, we can't schedule loop seeks preemptively,
+ // So if we start on EOF or Loop End, we let fillAndPushBuffer() adjust the sample count
+ if (fillAndPushBuffer(i, (i == 0)))
requestStop = true;
}
diff --git a/src/SFML/CMakeLists.txt b/src/SFML/CMakeLists.txt
index 8eb334d..25a5bb1 100644
--- a/src/SFML/CMakeLists.txt
+++ b/src/SFML/CMakeLists.txt
@@ -36,12 +36,9 @@ elseif(SFML_OS_IOS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
- set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}")
+ set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${CMAKE_ANDROID_ARCH_ABI}")
endif()
-# add the SFML sources path
-include_directories(${PROJECT_SOURCE_DIR}/src)
-
# define the path of our additional CMake modules
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
@@ -49,11 +46,31 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
# add the modules subdirectories
+
+# sfml-system
add_subdirectory(System)
+
+# sfml-main and sfml-activity
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS)
add_subdirectory(Main)
endif()
-add_subdirectory(Window)
-add_subdirectory(Network)
-add_subdirectory(Graphics)
-add_subdirectory(Audio)
+
+# sfml-window
+if(SFML_BUILD_WINDOW OR SFML_BUILD_GRAPHICS)
+ add_subdirectory(Window)
+endif()
+
+# sfml-network
+if(SFML_BUILD_NETWORK)
+ add_subdirectory(Network)
+endif()
+
+# sfml-graphics
+if(SFML_BUILD_GRAPHICS)
+ add_subdirectory(Graphics)
+endif()
+
+# sfml-audio
+if(SFML_BUILD_AUDIO)
+ add_subdirectory(Audio)
+endif()
diff --git a/src/SFML/Graphics/BlendMode.cpp b/src/SFML/Graphics/BlendMode.cpp
index ab69dcd..0d9cf95 100644
--- a/src/SFML/Graphics/BlendMode.cpp
+++ b/src/SFML/Graphics/BlendMode.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/CMakeLists.txt b/src/SFML/Graphics/CMakeLists.txt
index 57dfa80..883c758 100644
--- a/src/SFML/Graphics/CMakeLists.txt
+++ b/src/SFML/Graphics/CMakeLists.txt
@@ -72,6 +72,8 @@ set(DRAWABLES_SRC
${INCROOT}/Text.hpp
${SRCROOT}/VertexArray.cpp
${INCROOT}/VertexArray.hpp
+ ${SRCROOT}/VertexBuffer.cpp
+ ${INCROOT}/VertexBuffer.hpp
)
source_group("drawables" FILES ${DRAWABLES_SRC})
@@ -86,75 +88,60 @@ set(RENDER_TEXTURE_SRC
)
source_group("render texture" FILES ${RENDER_TEXTURE_SRC})
+
+# define the sfml-graphics target
+sfml_add_library(sfml-graphics
+ SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC})
+
+# setup dependencies
+target_link_libraries(sfml-graphics PUBLIC sfml-window)
+
# stb_image sources
-include_directories("${PROJECT_SOURCE_DIR}/extlibs/headers/stb_image")
+target_include_directories(sfml-graphics PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/stb_image")
# let CMake know about our additional graphics libraries paths
if(SFML_OS_WINDOWS)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/freetype2")
elseif(SFML_OS_MACOSX)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/freetype2")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
elseif(SFML_OS_IOS)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/freetype2")
elseif(SFML_OS_ANDROID)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/freetype2")
endif()
# find external libraries
-if(NOT SFML_OPENGL_ES)
- find_package(OpenGL REQUIRED)
+if(SFML_OPENGL_ES)
if(SFML_OS_LINUX)
- find_package(X11 REQUIRED)
+ sfml_find_package(EGL INCLUDE "EGL_INCLUDE_DIR" LINK "EGL_LIBRARY")
+ sfml_find_package(GLES INCLUDE "GLES_INCLUDE_DIR" LINK "GLES_LIBRARY")
+ target_link_libraries(sfml-graphics PRIVATE EGL GLES)
+ elseif(SFML_OS_IOS)
+ target_link_libraries(sfml-graphics PRIVATE "-framework OpenGLES")
endif()
- include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
-endif()
-if(SFML_OPENGL_ES AND SFML_OS_LINUX)
- find_package(EGL REQUIRED)
- find_package(GLES REQUIRED)
- include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
-endif()
-if(SFML_OS_ANDROID)
- find_host_package(JPEG REQUIRED)
- find_host_package(Freetype REQUIRED)
else()
- find_package(JPEG REQUIRED)
- find_package(Freetype REQUIRED)
-endif()
-include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
+ # Target OpenGL already defined for Window component so no sfml_find_package() here
+ target_link_libraries(sfml-graphics PRIVATE OpenGL)
-# build the list of external libraries to link
-if(NOT SFML_OPENGL_ES)
- list(APPEND GRAPHICS_EXT_LIBS ${OPENGL_gl_LIBRARY})
if(SFML_OS_LINUX)
- list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES})
+ # Target X11 already defined for Window component so no sfml_find_package() here
+ target_link_libraries(sfml-graphics PRIVATE X11)
endif()
endif()
-if(SFML_OPENGL_ES AND SFML_OS_LINUX)
- list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
-endif()
-if(SFML_OS_IOS)
- list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
-elseif(SFML_OS_ANDROID)
- list(APPEND GRAPHICS_EXT_LIBS z)
+
+if(SFML_OS_ANDROID)
+ target_link_libraries(sfml-graphics PRIVATE z EGL GLESv1_CM)
endif()
-list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
+
+sfml_find_package(Freetype INCLUDE "FREETYPE_INCLUDE_DIRS" LINK "FREETYPE_LIBRARY")
+target_link_libraries(sfml-graphics PRIVATE Freetype)
# add preprocessor symbols
-add_definitions(-DSTBI_FAILURE_USERMSG)
+target_compile_definitions(sfml-graphics PRIVATE "STBI_FAILURE_USERMSG")
# ImageLoader.cpp must be compiled with the -fno-strict-aliasing
# when gcc is used; otherwise saving PNGs may crash in stb_image_write
if(SFML_COMPILER_GCC)
set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
endif()
-
-# define the sfml-graphics target
-sfml_add_library(sfml-graphics
- SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC}
- DEPENDS sfml-window sfml-system
- EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS})
diff --git a/src/SFML/Graphics/CircleShape.cpp b/src/SFML/Graphics/CircleShape.cpp
index 8e55510..0cfa3c7 100644
--- a/src/SFML/Graphics/CircleShape.cpp
+++ b/src/SFML/Graphics/CircleShape.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Color.cpp b/src/SFML/Graphics/Color.cpp
index fdadb41..03f99a4 100644
--- a/src/SFML/Graphics/Color.cpp
+++ b/src/SFML/Graphics/Color.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/ConvexShape.cpp b/src/SFML/Graphics/ConvexShape.cpp
index 35ff135..56aa787 100644
--- a/src/SFML/Graphics/ConvexShape.cpp
+++ b/src/SFML/Graphics/ConvexShape.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp
index 53df89f..45f6baf 100644
--- a/src/SFML/Graphics/Font.cpp
+++ b/src/SFML/Graphics/Font.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -61,6 +61,21 @@ namespace
void close(FT_Stream)
{
}
+
+ // Helper to intepret memory as a specific type
+ template <typename T, typename U>
+ inline T reinterpret(const U& input)
+ {
+ T output;
+ std::memcpy(&output, &input, sizeof(U));
+ return output;
+ }
+
+ // Combine outline thickness, boldness and codepoint into a single 64-bit key
+ sf::Uint64 combine(float outlineThickness, bool bold, sf::Uint32 codePoint)
+ {
+ return (static_cast<sf::Uint64>(reinterpret<sf::Uint32>(outlineThickness)) << 32) | (static_cast<sf::Uint64>(bold) << 31) | codePoint;
+ }
}
@@ -151,19 +166,21 @@ bool Font::loadFromFile(const std::string& filename)
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
{
err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl;
+ FT_Done_Face(face);
return false;
}
- m_stroker = stroker;
// Select the unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{
err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl;
+ FT_Stroker_Done(stroker);
FT_Done_Face(face);
return false;
}
// Store the loaded font in our ugly void* :)
+ m_stroker = stroker;
m_face = face;
// Store the font information
@@ -214,19 +231,21 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
{
err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
+ FT_Done_Face(face);
return false;
}
- m_stroker = stroker;
// Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{
err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl;
+ FT_Stroker_Done(stroker);
FT_Done_Face(face);
return false;
}
// Store the loaded font in our ugly void* :)
+ m_stroker = stroker;
m_face = face;
// Store the font information
@@ -287,20 +306,23 @@ bool Font::loadFromStream(InputStream& stream)
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
{
err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
+ FT_Done_Face(face);
+ delete rec;
return false;
}
- m_stroker = stroker;
// Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{
err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl;
FT_Done_Face(face);
+ FT_Stroker_Done(stroker);
delete rec;
return false;
}
// Store the loaded font in our ugly void* :)
+ m_stroker = stroker;
m_face = face;
m_streamRec = rec;
@@ -325,9 +347,7 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
GlyphTable& glyphs = m_pages[characterSize].glyphs;
// Build the key by combining the code point, bold flag, and outline thickness
- Uint64 key = (static_cast<Uint64>(*reinterpret_cast<Uint32*>(&outlineThickness)) << 32)
- | (static_cast<Uint64>(bold ? 1 : 0) << 31)
- | static_cast<Uint64>(codePoint);
+ Uint64 key = combine(outlineThickness, bold, codePoint);
// Search the glyph into the cache
GlyphTable::const_iterator it = glyphs.find(key);
@@ -504,7 +524,7 @@ void Font::cleanup()
m_streamRec = NULL;
m_refCount = NULL;
m_pages.clear();
- m_pixelBuffer.clear();
+ std::vector<Uint8>().swap(m_pixelBuffer);
}
@@ -551,7 +571,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
FT_Stroker stroker = static_cast<FT_Stroker>(m_stroker);
FT_Stroker_Set(stroker, static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
- FT_Glyph_Stroke(&glyphDesc, stroker, false);
+ FT_Glyph_Stroke(&glyphDesc, stroker, true);
}
}
@@ -583,11 +603,14 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
// pollute them with pixels from neighbors
const unsigned int padding = 1;
+ width += 2 * padding;
+ height += 2 * padding;
+
// Get the glyphs page corresponding to the character size
Page& page = m_pages[characterSize];
// Find a good position for the new glyph into the texture
- glyph.textureRect = findGlyphRect(page, width + 2 * padding, height + 2 * padding);
+ glyph.textureRect = findGlyphRect(page, width, height);
// Make sure the texture data is positioned in the center
// of the allocated texture rectangle
@@ -602,19 +625,32 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
glyph.bounds.width = static_cast<float>(face->glyph->metrics.width) / static_cast<float>(1 << 6) + outlineThickness * 2;
glyph.bounds.height = static_cast<float>(face->glyph->metrics.height) / static_cast<float>(1 << 6) + outlineThickness * 2;
+ // Resize the pixel buffer to the new size and fill it with transparent white pixels
+ m_pixelBuffer.resize(width * height * 4);
+
+ Uint8* current = &m_pixelBuffer[0];
+ Uint8* end = current + width * height * 4;
+
+ while (current != end)
+ {
+ (*current++) = 255;
+ (*current++) = 255;
+ (*current++) = 255;
+ (*current++) = 0;
+ }
+
// Extract the glyph's pixels from the bitmap
- m_pixelBuffer.resize(width * height * 4, 255);
const Uint8* pixels = bitmap.buffer;
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
{
// Pixels are 1 bit monochrome values
- for (int y = 0; y < height; ++y)
+ for (unsigned int y = padding; y < height - padding; ++y)
{
- for (int x = 0; x < width; ++x)
+ for (unsigned int x = padding; x < width - padding; ++x)
{
// The color channels remain white, just fill the alpha channel
- std::size_t index = (x + y * width) * 4 + 3;
- m_pixelBuffer[index] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0;
+ std::size_t index = x + y * width;
+ m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0;
}
pixels += bitmap.pitch;
}
@@ -622,23 +658,23 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
else
{
// Pixels are 8 bits gray levels
- for (int y = 0; y < height; ++y)
+ for (unsigned int y = padding; y < height - padding; ++y)
{
- for (int x = 0; x < width; ++x)
+ for (unsigned int x = padding; x < width - padding; ++x)
{
// The color channels remain white, just fill the alpha channel
- std::size_t index = (x + y * width) * 4 + 3;
- m_pixelBuffer[index] = pixels[x];
+ std::size_t index = x + y * width;
+ m_pixelBuffer[index * 4 + 3] = pixels[x - padding];
}
pixels += bitmap.pitch;
}
}
// Write the pixels to the texture
- unsigned int x = glyph.textureRect.left;
- unsigned int y = glyph.textureRect.top;
- unsigned int w = glyph.textureRect.width;
- unsigned int h = glyph.textureRect.height;
+ unsigned int x = glyph.textureRect.left - padding;
+ unsigned int y = glyph.textureRect.top - padding;
+ unsigned int w = glyph.textureRect.width + 2 * padding;
+ unsigned int h = glyph.textureRect.height + 2 * padding;
page.texture.update(&m_pixelBuffer[0], w, h, x, y);
}
@@ -689,10 +725,10 @@ IntRect Font::findGlyphRect(Page& page, unsigned int width, unsigned int height)
if ((textureWidth * 2 <= Texture::getMaximumSize()) && (textureHeight * 2 <= Texture::getMaximumSize()))
{
// Make the texture 2 times bigger
- Image newImage;
- newImage.create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0));
- newImage.copy(page.texture.copyToImage(), 0, 0);
- page.texture.loadFromImage(newImage);
+ Texture newTexture;
+ newTexture.create(textureWidth * 2, textureHeight * 2);
+ newTexture.update(page.texture);
+ page.texture.swap(newTexture);
}
else
{
diff --git a/src/SFML/Graphics/GLCheck.cpp b/src/SFML/Graphics/GLCheck.cpp
index 85d9854..580e838 100644
--- a/src/SFML/Graphics/GLCheck.cpp
+++ b/src/SFML/Graphics/GLCheck.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/GLCheck.hpp b/src/SFML/Graphics/GLCheck.hpp
index 2b5fa7d..86b96de 100644
--- a/src/SFML/Graphics/GLCheck.hpp
+++ b/src/SFML/Graphics/GLCheck.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/GLExtensions.cpp b/src/SFML/Graphics/GLExtensions.cpp
index 57f5bcc..fff712d 100644
--- a/src/SFML/Graphics/GLExtensions.cpp
+++ b/src/SFML/Graphics/GLExtensions.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/GLExtensions.hpp b/src/SFML/Graphics/GLExtensions.hpp
index 2110bd9..687cf37 100644
--- a/src/SFML/Graphics/GLExtensions.hpp
+++ b/src/SFML/Graphics/GLExtensions.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -53,6 +53,19 @@
#define GLEXT_GL_CLAMP GL_CLAMP_TO_EDGE
#define GLEXT_GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE
+ // Core since 1.1
+ // 1.1 does not support GL_STREAM_DRAW so we just define it to GL_DYNAMIC_DRAW
+ #define GLEXT_vertex_buffer_object true
+ #define GLEXT_GL_ARRAY_BUFFER GL_ARRAY_BUFFER
+ #define GLEXT_GL_DYNAMIC_DRAW GL_DYNAMIC_DRAW
+ #define GLEXT_GL_STATIC_DRAW GL_STATIC_DRAW
+ #define GLEXT_GL_STREAM_DRAW GL_DYNAMIC_DRAW
+ #define GLEXT_glBindBuffer glBindBuffer
+ #define GLEXT_glBufferData glBufferData
+ #define GLEXT_glBufferSubData glBufferSubData
+ #define GLEXT_glDeleteBuffers glDeleteBuffers
+ #define GLEXT_glGenBuffers glGenBuffers
+
// The following extensions are listed chronologically
// Extension macro first, followed by tokens then
// functions according to the corresponding specification
@@ -111,6 +124,18 @@
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
+ // Core since 3.0
+ #define GLEXT_packed_depth_stencil false
+
+ // Core since 3.0
+ #define GLEXT_framebuffer_blit false
+
+ // Core since 3.0
+ #define GLEXT_framebuffer_multisample false
+
+ // Core since 3.0 - NV_copy_buffer
+ #define GLEXT_copy_buffer false
+
// Core since 3.0 - EXT_sRGB
#ifdef GL_EXT_sRGB
#define GLEXT_texture_sRGB GL_EXT_sRGB
@@ -165,6 +190,22 @@
#define GLEXT_blend_func_separate sfogl_ext_EXT_blend_func_separate
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
+ // Core since 1.5 - ARB_vertex_buffer_object
+ #define GLEXT_vertex_buffer_object sfogl_ext_ARB_vertex_buffer_object
+ #define GLEXT_GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
+ #define GLEXT_GL_DYNAMIC_DRAW GL_DYNAMIC_DRAW_ARB
+ #define GLEXT_GL_READ_ONLY GL_READ_ONLY_ARB
+ #define GLEXT_GL_STATIC_DRAW GL_STATIC_DRAW_ARB
+ #define GLEXT_GL_STREAM_DRAW GL_STREAM_DRAW_ARB
+ #define GLEXT_GL_WRITE_ONLY GL_WRITE_ONLY_ARB
+ #define GLEXT_glBindBuffer glBindBufferARB
+ #define GLEXT_glBufferData glBufferDataARB
+ #define GLEXT_glBufferSubData glBufferSubDataARB
+ #define GLEXT_glDeleteBuffers glDeleteBuffersARB
+ #define GLEXT_glGenBuffers glGenBuffersARB
+ #define GLEXT_glMapBuffer glMapBufferARB
+ #define GLEXT_glUnmapBuffer glUnmapBufferARB
+
// Core since 2.0 - ARB_shading_language_100
#define GLEXT_shading_language_100 sfogl_ext_ARB_shading_language_100
@@ -242,6 +283,30 @@
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
+ #define GLEXT_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
+
+ // Core since 3.0 - EXT_packed_depth_stencil
+ #define GLEXT_packed_depth_stencil sfogl_ext_EXT_packed_depth_stencil
+ #define GLEXT_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
+
+ // Core since 3.0 - EXT_framebuffer_blit
+ #define GLEXT_framebuffer_blit sfogl_ext_EXT_framebuffer_blit
+ #define GLEXT_glBlitFramebuffer glBlitFramebufferEXT
+ #define GLEXT_GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_EXT
+ #define GLEXT_GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_EXT
+ #define GLEXT_GL_DRAW_FRAMEBUFFER_BINDING GL_DRAW_FRAMEBUFFER_BINDING_EXT
+ #define GLEXT_GL_READ_FRAMEBUFFER_BINDING GL_READ_FRAMEBUFFER_BINDING_EXT
+
+ // Core since 3.0 - EXT_framebuffer_multisample
+ #define GLEXT_framebuffer_multisample sfogl_ext_EXT_framebuffer_multisample
+ #define GLEXT_glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
+ #define GLEXT_GL_MAX_SAMPLES GL_MAX_SAMPLES_EXT
+
+ // Core since 3.1 - ARB_copy_buffer
+ #define GLEXT_copy_buffer sfogl_ext_ARB_copy_buffer
+ #define GLEXT_GL_COPY_READ_BUFFER GL_COPY_READ_BUFFER
+ #define GLEXT_GL_COPY_WRITE_BUFFER GL_COPY_WRITE_BUFFER
+ #define GLEXT_glCopyBufferSubData glCopyBufferSubData
// Core since 3.2 - ARB_geometry_shader4
#define GLEXT_geometry_shader4 sfogl_ext_ARB_geometry_shader4
diff --git a/src/SFML/Graphics/GLExtensions.txt b/src/SFML/Graphics/GLExtensions.txt
index 5b62027..e12e809 100644
--- a/src/SFML/Graphics/GLExtensions.txt
+++ b/src/SFML/Graphics/GLExtensions.txt
@@ -7,6 +7,7 @@ EXT_blend_minmax
EXT_blend_subtract
ARB_multitexture
EXT_blend_func_separate
+ARB_vertex_buffer_object
ARB_shading_language_100
ARB_shader_objects
ARB_vertex_shader
@@ -15,4 +16,8 @@ ARB_texture_non_power_of_two
EXT_blend_equation_separate
EXT_texture_sRGB
EXT_framebuffer_object
+EXT_packed_depth_stencil
+EXT_framebuffer_blit
+EXT_framebuffer_multisample
+ARB_copy_buffer
ARB_geometry_shader4
diff --git a/src/SFML/Graphics/GLLoader.cpp b/src/SFML/Graphics/GLLoader.cpp
index 40bc84c..85f6d7e 100644
--- a/src/SFML/Graphics/GLLoader.cpp
+++ b/src/SFML/Graphics/GLLoader.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -39,6 +39,7 @@ int sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_func_separate = sfogl_LOAD_FAILED;
+int sfogl_ext_ARB_vertex_buffer_object = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_shading_language_100 = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_shader_objects = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_vertex_shader = sfogl_LOAD_FAILED;
@@ -47,6 +48,10 @@ int sfogl_ext_ARB_texture_non_power_of_two = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
+int sfogl_ext_EXT_packed_depth_stencil = sfogl_LOAD_FAILED;
+int sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
+int sfogl_ext_EXT_framebuffer_multisample = sfogl_LOAD_FAILED;
+int sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
void (GL_FUNCPTR *sf_ptrc_glBlendEquationEXT)(GLenum) = NULL;
@@ -253,6 +258,69 @@ static int Load_EXT_blend_func_separate()
return numFailed;
}
+void (GL_FUNCPTR *sf_ptrc_glBindBufferARB)(GLenum, GLuint) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glBufferDataARB)(GLenum, GLsizeiptrARB, const void*, GLenum) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, const void*) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glDeleteBuffersARB)(GLsizei, const GLuint*) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glGenBuffersARB)(GLsizei, GLuint*) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glGetBufferParameterivARB)(GLenum, GLenum, GLint*) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glGetBufferPointervARB)(GLenum, GLenum, void**) = NULL;
+void (GL_FUNCPTR *sf_ptrc_glGetBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, void*) = NULL;
+GLboolean (GL_FUNCPTR *sf_ptrc_glIsBufferARB)(GLuint) = NULL;
+void* (GL_FUNCPTR *sf_ptrc_glMapBufferARB)(GLenum, GLenum) = NULL;
+GLboolean (GL_FUNCPTR *sf_ptrc_glUnmapBufferARB)(GLenum) = NULL;
+
+static int Load_ARB_vertex_buffer_object()
+{
+ int numFailed = 0;
+
+ sf_ptrc_glBindBufferARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLuint)>(glLoaderGetProcAddress("glBindBufferARB"));
+ if (!sf_ptrc_glBindBufferARB)
+ numFailed++;
+
+ sf_ptrc_glBufferDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLsizeiptrARB, const void*, GLenum)>(glLoaderGetProcAddress("glBufferDataARB"));
+ if (!sf_ptrc_glBufferDataARB)
+ numFailed++;
+
+ sf_ptrc_glBufferSubDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLintptrARB, GLsizeiptrARB, const void*)>(glLoaderGetProcAddress("glBufferSubDataARB"));
+ if (!sf_ptrc_glBufferSubDataARB)
+ numFailed++;
+
+ sf_ptrc_glDeleteBuffersARB = reinterpret_cast<void (GL_FUNCPTR *)(GLsizei, const GLuint*)>(glLoaderGetProcAddress("glDeleteBuffersARB"));
+ if (!sf_ptrc_glDeleteBuffersARB)
+ numFailed++;
+
+ sf_ptrc_glGenBuffersARB = reinterpret_cast<void (GL_FUNCPTR *)(GLsizei, GLuint*)>(glLoaderGetProcAddress("glGenBuffersARB"));
+ if (!sf_ptrc_glGenBuffersARB)
+ numFailed++;
+
+ sf_ptrc_glGetBufferParameterivARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLint*)>(glLoaderGetProcAddress("glGetBufferParameterivARB"));
+ if (!sf_ptrc_glGetBufferParameterivARB)
+ numFailed++;
+
+ sf_ptrc_glGetBufferPointervARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, void**)>(glLoaderGetProcAddress("glGetBufferPointervARB"));
+ if (!sf_ptrc_glGetBufferPointervARB)
+ numFailed++;
+
+ sf_ptrc_glGetBufferSubDataARB = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLintptrARB, GLsizeiptrARB, void*)>(glLoaderGetProcAddress("glGetBufferSubDataARB"));
+ if (!sf_ptrc_glGetBufferSubDataARB)
+ numFailed++;
+
+ sf_ptrc_glIsBufferARB = reinterpret_cast<GLboolean (GL_FUNCPTR *)(GLuint)>(glLoaderGetProcAddress("glIsBufferARB"));
+ if (!sf_ptrc_glIsBufferARB)
+ numFailed++;
+
+ sf_ptrc_glMapBufferARB = reinterpret_cast<void* (GL_FUNCPTR *)(GLenum, GLenum)>(glLoaderGetProcAddress("glMapBufferARB"));
+ if (!sf_ptrc_glMapBufferARB)
+ numFailed++;
+
+ sf_ptrc_glUnmapBufferARB = reinterpret_cast<GLboolean (GL_FUNCPTR *)(GLenum)>(glLoaderGetProcAddress("glUnmapBufferARB"));
+ if (!sf_ptrc_glUnmapBufferARB)
+ numFailed++;
+
+ return numFailed;
+}
+
void (GL_FUNCPTR *sf_ptrc_glAttachObjectARB)(GLhandleARB, GLhandleARB) = NULL;
void (GL_FUNCPTR *sf_ptrc_glCompileShaderARB)(GLhandleARB) = NULL;
GLhandleARB (GL_FUNCPTR *sf_ptrc_glCreateProgramObjectARB)() = NULL;
@@ -800,6 +868,45 @@ static int Load_EXT_framebuffer_object()
return numFailed;
}
+void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum) = NULL;
+
+static int Load_EXT_framebuffer_blit()
+{
+ int numFailed = 0;
+
+ sf_ptrc_glBlitFramebufferEXT = reinterpret_cast<void (GL_FUNCPTR *)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)>(glLoaderGetProcAddress("glBlitFramebufferEXT"));
+ if (!sf_ptrc_glBlitFramebufferEXT)
+ numFailed++;
+
+ return numFailed;
+}
+
+void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = NULL;
+
+static int Load_EXT_framebuffer_multisample()
+{
+ int numFailed = 0;
+
+ sf_ptrc_glRenderbufferStorageMultisampleEXT = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(glLoaderGetProcAddress("glRenderbufferStorageMultisampleEXT"));
+ if (!sf_ptrc_glRenderbufferStorageMultisampleEXT)
+ numFailed++;
+
+ return numFailed;
+}
+
+void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr) = NULL;
+
+static int Load_ARB_copy_buffer()
+{
+ int numFailed = 0;
+
+ sf_ptrc_glCopyBufferSubData = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr)>(glLoaderGetProcAddress("glCopyBufferSubData"));
+ if (!sf_ptrc_glCopyBufferSubData)
+ numFailed++;
+
+ return numFailed;
+}
+
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint) = NULL;
@@ -836,13 +943,14 @@ typedef struct sfogl_StrToExtMap_s
PFN_LOADFUNCPOINTERS LoadExtension;
} sfogl_StrToExtMap;
-static sfogl_StrToExtMap ExtensionMap[15] = {
+static sfogl_StrToExtMap ExtensionMap[20] = {
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
{"GL_EXT_blend_subtract", &sfogl_ext_EXT_blend_subtract, NULL},
{"GL_ARB_multitexture", &sfogl_ext_ARB_multitexture, Load_ARB_multitexture},
{"GL_EXT_blend_func_separate", &sfogl_ext_EXT_blend_func_separate, Load_EXT_blend_func_separate},
+ {"GL_ARB_vertex_buffer_object", &sfogl_ext_ARB_vertex_buffer_object, Load_ARB_vertex_buffer_object},
{"GL_ARB_shading_language_100", &sfogl_ext_ARB_shading_language_100, NULL},
{"GL_ARB_shader_objects", &sfogl_ext_ARB_shader_objects, Load_ARB_shader_objects},
{"GL_ARB_vertex_shader", &sfogl_ext_ARB_vertex_shader, Load_ARB_vertex_shader},
@@ -851,10 +959,14 @@ static sfogl_StrToExtMap ExtensionMap[15] = {
{"GL_EXT_blend_equation_separate", &sfogl_ext_EXT_blend_equation_separate, Load_EXT_blend_equation_separate},
{"GL_EXT_texture_sRGB", &sfogl_ext_EXT_texture_sRGB, NULL},
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object},
+ {"GL_EXT_packed_depth_stencil", &sfogl_ext_EXT_packed_depth_stencil, NULL},
+ {"GL_EXT_framebuffer_blit", &sfogl_ext_EXT_framebuffer_blit, Load_EXT_framebuffer_blit},
+ {"GL_EXT_framebuffer_multisample", &sfogl_ext_EXT_framebuffer_multisample, Load_EXT_framebuffer_multisample},
+ {"GL_ARB_copy_buffer", &sfogl_ext_ARB_copy_buffer, Load_ARB_copy_buffer},
{"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4}
};
-static int g_extensionMapSize = 15;
+static int g_extensionMapSize = 20;
static void ClearExtensionVars()
@@ -865,6 +977,7 @@ static void ClearExtensionVars()
sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
sfogl_ext_EXT_blend_func_separate = sfogl_LOAD_FAILED;
+ sfogl_ext_ARB_vertex_buffer_object = sfogl_LOAD_FAILED;
sfogl_ext_ARB_shading_language_100 = sfogl_LOAD_FAILED;
sfogl_ext_ARB_shader_objects = sfogl_LOAD_FAILED;
sfogl_ext_ARB_vertex_shader = sfogl_LOAD_FAILED;
@@ -873,6 +986,10 @@ static void ClearExtensionVars()
sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
+ sfogl_ext_EXT_packed_depth_stencil = sfogl_LOAD_FAILED;
+ sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
+ sfogl_ext_EXT_framebuffer_multisample = sfogl_LOAD_FAILED;
+ sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
}
diff --git a/src/SFML/Graphics/GLLoader.hpp b/src/SFML/Graphics/GLLoader.hpp
index fb3f9b3..9fe4adb 100644
--- a/src/SFML/Graphics/GLLoader.hpp
+++ b/src/SFML/Graphics/GLLoader.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -176,6 +176,7 @@ extern int sfogl_ext_EXT_blend_minmax;
extern int sfogl_ext_EXT_blend_subtract;
extern int sfogl_ext_ARB_multitexture;
extern int sfogl_ext_EXT_blend_func_separate;
+extern int sfogl_ext_ARB_vertex_buffer_object;
extern int sfogl_ext_ARB_shading_language_100;
extern int sfogl_ext_ARB_shader_objects;
extern int sfogl_ext_ARB_vertex_shader;
@@ -184,6 +185,10 @@ extern int sfogl_ext_ARB_texture_non_power_of_two;
extern int sfogl_ext_EXT_blend_equation_separate;
extern int sfogl_ext_EXT_texture_sRGB;
extern int sfogl_ext_EXT_framebuffer_object;
+extern int sfogl_ext_EXT_packed_depth_stencil;
+extern int sfogl_ext_EXT_framebuffer_blit;
+extern int sfogl_ext_EXT_framebuffer_multisample;
+extern int sfogl_ext_ARB_copy_buffer;
extern int sfogl_ext_ARB_geometry_shader4;
#define GL_CLAMP_TO_EDGE_SGIS 0x812F
@@ -239,6 +244,38 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_WRITE_ONLY_ARB 0x88B9
+
#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
#define GL_BOOL_ARB 0x8B56
@@ -379,6 +416,23 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_STENCIL_INDEX4_EXT 0x8D47
#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+
#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
@@ -1016,6 +1070,32 @@ extern void (GL_FUNCPTR *sf_ptrc_glBlendFuncSeparateEXT)(GLenum, GLenum, GLenum,
#define glBlendFuncSeparateEXT sf_ptrc_glBlendFuncSeparateEXT
#endif // GL_EXT_blend_func_separate
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+extern void (GL_FUNCPTR *sf_ptrc_glBindBufferARB)(GLenum, GLuint);
+#define glBindBufferARB sf_ptrc_glBindBufferARB
+extern void (GL_FUNCPTR *sf_ptrc_glBufferDataARB)(GLenum, GLsizeiptrARB, const void*, GLenum);
+#define glBufferDataARB sf_ptrc_glBufferDataARB
+extern void (GL_FUNCPTR *sf_ptrc_glBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, const void*);
+#define glBufferSubDataARB sf_ptrc_glBufferSubDataARB
+extern void (GL_FUNCPTR *sf_ptrc_glDeleteBuffersARB)(GLsizei, const GLuint*);
+#define glDeleteBuffersARB sf_ptrc_glDeleteBuffersARB
+extern void (GL_FUNCPTR *sf_ptrc_glGenBuffersARB)(GLsizei, GLuint*);
+#define glGenBuffersARB sf_ptrc_glGenBuffersARB
+extern void (GL_FUNCPTR *sf_ptrc_glGetBufferParameterivARB)(GLenum, GLenum, GLint*);
+#define glGetBufferParameterivARB sf_ptrc_glGetBufferParameterivARB
+extern void (GL_FUNCPTR *sf_ptrc_glGetBufferPointervARB)(GLenum, GLenum, void**);
+#define glGetBufferPointervARB sf_ptrc_glGetBufferPointervARB
+extern void (GL_FUNCPTR *sf_ptrc_glGetBufferSubDataARB)(GLenum, GLintptrARB, GLsizeiptrARB, void*);
+#define glGetBufferSubDataARB sf_ptrc_glGetBufferSubDataARB
+extern GLboolean (GL_FUNCPTR *sf_ptrc_glIsBufferARB)(GLuint);
+#define glIsBufferARB sf_ptrc_glIsBufferARB
+extern void* (GL_FUNCPTR *sf_ptrc_glMapBufferARB)(GLenum, GLenum);
+#define glMapBufferARB sf_ptrc_glMapBufferARB
+extern GLboolean (GL_FUNCPTR *sf_ptrc_glUnmapBufferARB)(GLenum);
+#define glUnmapBufferARB sf_ptrc_glUnmapBufferARB
+#endif // GL_ARB_vertex_buffer_object
+
#ifndef GL_ARB_shader_objects
#define GL_ARB_shader_objects 1
@@ -1242,6 +1322,25 @@ extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageEXT)(GLenum, GLenum, GLsiz
#define glRenderbufferStorageEXT sf_ptrc_glRenderbufferStorageEXT
#endif // GL_EXT_framebuffer_object
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+extern void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+#define glBlitFramebufferEXT sf_ptrc_glBlitFramebufferEXT
+#endif // GL_EXT_framebuffer_blit
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+#define glRenderbufferStorageMultisampleEXT sf_ptrc_glRenderbufferStorageMultisampleEXT
+#endif // GL_EXT_framebuffer_multisample
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+extern void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);
+#define glCopyBufferSubData sf_ptrc_glCopyBufferSubData
+#endif // GL_ARB_copy_buffer
+
#ifndef GL_ARB_geometry_shader4
#define GL_ARB_geometry_shader4 1
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint);
diff --git a/src/SFML/Graphics/Glsl.cpp b/src/SFML/Graphics/Glsl.cpp
index c5d2b78..e8f9c1e 100644
--- a/src/SFML/Graphics/Glsl.cpp
+++ b/src/SFML/Graphics/Glsl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp
index 8dae99b..67c2840 100644
--- a/src/SFML/Graphics/Image.cpp
+++ b/src/SFML/Graphics/Image.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -41,23 +41,14 @@ namespace sf
Image::Image() :
m_size(0, 0)
{
- #ifdef SFML_SYSTEM_ANDROID
- m_stream = NULL;
-
- #endif
}
////////////////////////////////////////////////////////////
Image::~Image()
{
- #ifdef SFML_SYSTEM_ANDROID
-
- if (m_stream)
- delete (priv::ResourceStream*)m_stream;
- #endif
}
@@ -135,11 +126,8 @@ bool Image::loadFromFile(const std::string& filename)
#else
- if (m_stream)
- delete (priv::ResourceStream*)m_stream;
-
- m_stream = new priv::ResourceStream(filename);
- return loadFromStream(*(priv::ResourceStream*)m_stream);
+ priv::ResourceStream stream(filename);
+ return loadFromStream(stream);
#endif
}
diff --git a/src/SFML/Graphics/ImageLoader.cpp b/src/SFML/Graphics/ImageLoader.cpp
index 15d50d9..023541d 100644
--- a/src/SFML/Graphics/ImageLoader.cpp
+++ b/src/SFML/Graphics/ImageLoader.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -32,11 +32,6 @@
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
-extern "C"
-{
- #include <jpeglib.h>
- #include <jerror.h>
-}
#include <cctype>
@@ -268,7 +263,7 @@ bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector
else if (extension == "jpg" || extension == "jpeg")
{
// JPG format
- if (writeJpg(filename, pixels, size.x, size.y))
+ if (stbi_write_jpg(filename.c_str(), size.x, size.y, 4, &pixels[0], 90))
return true;
}
}
@@ -277,60 +272,6 @@ bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector
return false;
}
-
-////////////////////////////////////////////////////////////
-bool ImageLoader::writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
-{
- // Open the file to write in
- FILE* file = fopen(filename.c_str(), "wb");
- if (!file)
- return false;
-
- // Initialize the error handler
- jpeg_compress_struct compressInfos;
- jpeg_error_mgr errorManager;
- compressInfos.err = jpeg_std_error(&errorManager);
-
- // Initialize all the writing and compression infos
- jpeg_create_compress(&compressInfos);
- compressInfos.image_width = width;
- compressInfos.image_height = height;
- compressInfos.input_components = 3;
- compressInfos.in_color_space = JCS_RGB;
- jpeg_stdio_dest(&compressInfos, file);
- jpeg_set_defaults(&compressInfos);
- jpeg_set_quality(&compressInfos, 90, TRUE);
-
- // Get rid of the alpha channel
- std::vector<Uint8> buffer(width * height * 3);
- for (std::size_t i = 0; i < width * height; ++i)
- {
- buffer[i * 3 + 0] = pixels[i * 4 + 0];
- buffer[i * 3 + 1] = pixels[i * 4 + 1];
- buffer[i * 3 + 2] = pixels[i * 4 + 2];
- }
- Uint8* ptr = &buffer[0];
-
- // Start compression
- jpeg_start_compress(&compressInfos, TRUE);
-
- // Write each row of the image
- while (compressInfos.next_scanline < compressInfos.image_height)
- {
- JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3);
- jpeg_write_scanlines(&compressInfos, &rawPointer, 1);
- }
-
- // Finish compression
- jpeg_finish_compress(&compressInfos);
- jpeg_destroy_compress(&compressInfos);
-
- // Close the file
- fclose(file);
-
- return true;
-}
-
} // namespace priv
} // namespace sf
diff --git a/src/SFML/Graphics/ImageLoader.hpp b/src/SFML/Graphics/ImageLoader.hpp
index adcd3d8..0134bd8 100644
--- a/src/SFML/Graphics/ImageLoader.hpp
+++ b/src/SFML/Graphics/ImageLoader.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -118,19 +118,6 @@ private:
///
////////////////////////////////////////////////////////////
~ImageLoader();
-
- ////////////////////////////////////////////////////////////
- /// \brief Save an image file in JPEG format
- ///
- /// \param filename Path of image file to save
- /// \param pixels Array of pixels to save to image
- /// \param width Width of image to save, in pixels
- /// \param height Height of image to save, in pixels
- ///
- /// \return True if saving was successful
- ///
- ////////////////////////////////////////////////////////////
- bool writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
};
} // namespace priv
diff --git a/src/SFML/Graphics/RectangleShape.cpp b/src/SFML/Graphics/RectangleShape.cpp
index abe1187..f7778c0 100644
--- a/src/SFML/Graphics/RectangleShape.cpp
+++ b/src/SFML/Graphics/RectangleShape.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/RenderStates.cpp b/src/SFML/Graphics/RenderStates.cpp
index bc45103..4c55546 100644
--- a/src/SFML/Graphics/RenderStates.cpp
+++ b/src/SFML/Graphics/RenderStates.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp
index 700c884..7eccf82 100644
--- a/src/SFML/Graphics/RenderTarget.cpp
+++ b/src/SFML/Graphics/RenderTarget.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -30,13 +30,58 @@
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/VertexArray.hpp>
+#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
+#include <SFML/Window/Context.hpp>
+#include <SFML/System/Mutex.hpp>
+#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <iostream>
+#include <algorithm>
+#include <map>
+
+
+// GL_QUADS is unavailable on OpenGL ES, thus we need to define GL_QUADS ourselves
+#ifdef SFML_OPENGL_ES
+
+ #define GL_QUADS 0
+
+#endif // SFML_OPENGL_ES
+
namespace
{
+ // Mutex to protect ID generation and our context-RenderTarget-map
+ sf::Mutex mutex;
+
+ // Unique identifier, used for identifying RenderTargets when
+ // tracking the currently active RenderTarget within a given context
+ sf::Uint64 getUniqueId()
+ {
+ sf::Lock lock(mutex);
+
+ static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget"
+
+ return id++;
+ }
+
+ // Map to help us detect whether a different RenderTarget
+ // has been activated within a single context
+ typedef std::map<sf::Uint64, sf::Uint64> ContextRenderTargetMap;
+ ContextRenderTargetMap contextRenderTargetMap;
+
+ // Check if a RenderTarget with the given ID is active in the current context
+ bool isActive(sf::Uint64 id)
+ {
+ ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(sf::Context::getActiveContextId());
+
+ if ((iter == contextRenderTargetMap.end()) || (iter->second != id))
+ return false;
+
+ return true;
+ }
+
// Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant.
sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor)
{
@@ -83,7 +128,8 @@ namespace sf
RenderTarget::RenderTarget() :
m_defaultView(),
m_view (),
-m_cache ()
+m_cache (),
+m_id (getUniqueId())
{
m_cache.glStatesSet = false;
}
@@ -98,7 +144,7 @@ RenderTarget::~RenderTarget()
////////////////////////////////////////////////////////////
void RenderTarget::clear(const Color& color)
{
- if (activate(true))
+ if (isActive(m_id) || setActive(true))
{
// Unbind texture to fix RenderTexture preventing clear
applyTexture(NULL);
@@ -211,17 +257,13 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl;
return;
}
- #define GL_QUADS 0
#endif
- if (activate(true))
+ if (isActive(m_id) || setActive(true))
{
- // First set the persistent OpenGL states if it's the very first call
- if (!m_cache.glStatesSet)
- resetGLStates();
-
// Check if the vertex count is low enough so that we can pre-transform them
bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
+
if (useVertexCache)
{
// Pre-transform the vertices and store them into the vertex cache
@@ -232,79 +274,163 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
vertex.color = vertices[i].color;
vertex.texCoords = vertices[i].texCoords;
}
-
- // Since vertices are transformed, we must use an identity transform to render them
- if (!m_cache.useVertexCache)
- applyTransform(Transform::Identity);
- }
- else
- {
- applyTransform(states.transform);
}
- // Apply the view
- if (m_cache.viewChanged)
- applyCurrentView();
+ setupDraw(useVertexCache, states);
- // Apply the blend mode
- if (states.blendMode != m_cache.lastBlendMode)
- applyBlendMode(states.blendMode);
-
- // Apply the texture
- Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
- if (textureId != m_cache.lastTextureId)
- applyTexture(states.texture);
-
- // Apply the shader
- if (states.shader)
- applyShader(states.shader);
-
- // If we pre-transform the vertices, we must use our internal vertex cache
- if (useVertexCache)
+ // Check if texture coordinates array is needed, and update client state accordingly
+ bool enableTexCoordsArray = (states.texture || states.shader);
+ if (!m_cache.enable || (enableTexCoordsArray != m_cache.texCoordsArrayEnabled))
{
- // ... and if we already used it previously, we don't need to set the pointers again
- if (!m_cache.useVertexCache)
- vertices = m_cache.vertexCache;
+ if (enableTexCoordsArray)
+ glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
else
- vertices = NULL;
+ glCheck(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
}
- // Setup the pointers to the vertices' components
- if (vertices)
+ // If we switch between non-cache and cache mode or enable texture
+ // coordinates we need to set up the pointers to the vertices' components
+ if (!m_cache.enable || !useVertexCache || !m_cache.useVertexCache)
{
const char* data = reinterpret_cast<const char*>(vertices);
+
+ // If we pre-transform the vertices, we must use our internal vertex cache
+ if (useVertexCache)
+ data = reinterpret_cast<const char*>(m_cache.vertexCache);
+
glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0));
glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8));
+ if (enableTexCoordsArray)
+ glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12));
+ }
+ else if (enableTexCoordsArray && !m_cache.texCoordsArrayEnabled)
+ {
+ // If we enter this block, we are already using our internal vertex cache
+ const char* data = reinterpret_cast<const char*>(m_cache.vertexCache);
+
glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12));
}
- // Find the OpenGL primitive type
- static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
- GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
- GLenum mode = modes[type];
+ drawPrimitives(type, 0, vertexCount);
+ cleanupDraw(states);
- // Draw the primitives
- glCheck(glDrawArrays(mode, 0, vertexCount));
+ // Update the cache
+ m_cache.useVertexCache = useVertexCache;
+ m_cache.texCoordsArrayEnabled = enableTexCoordsArray;
+ }
+}
- // Unbind the shader, if any
- if (states.shader)
- applyShader(NULL);
- // If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture.
- // This prevents a bug where some drivers do not clear RenderTextures properly.
- if (states.texture && states.texture->m_fboAttachment)
- applyTexture(NULL);
+////////////////////////////////////////////////////////////
+void RenderTarget::draw(const VertexBuffer& vertexBuffer, const RenderStates& states)
+{
+ draw(vertexBuffer, 0, vertexBuffer.getVertexCount(), states);
+}
+
+
+////////////////////////////////////////////////////////////
+void RenderTarget::draw(const VertexBuffer& vertexBuffer, std::size_t firstVertex,
+ std::size_t vertexCount, const RenderStates& states)
+{
+ // VertexBuffer not supported?
+ if (!VertexBuffer::isAvailable())
+ {
+ err() << "sf::VertexBuffer is not available, drawing skipped" << std::endl;
+ return;
+ }
+
+ // Sanity check
+ if (firstVertex > vertexBuffer.getVertexCount())
+ return;
+
+ // Clamp vertexCount to something that makes sense
+ vertexCount = std::min(vertexCount, vertexBuffer.getVertexCount() - firstVertex);
+
+ // Nothing to draw?
+ if (!vertexCount || !vertexBuffer.getNativeHandle())
+ return;
+
+ // GL_QUADS is unavailable on OpenGL ES
+ #ifdef SFML_OPENGL_ES
+ if (vertexBuffer.getPrimitiveType() == Quads)
+ {
+ err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl;
+ return;
+ }
+ #endif
+
+ if (isActive(m_id) || setActive(true))
+ {
+ setupDraw(false, states);
+
+ // Bind vertex buffer
+ VertexBuffer::bind(&vertexBuffer);
+
+ // Always enable texture coordinates
+ if (!m_cache.enable || !m_cache.texCoordsArrayEnabled)
+ glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
+
+ glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<const void*>(0)));
+ glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), reinterpret_cast<const void*>(8)));
+ glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<const void*>(12)));
+
+ drawPrimitives(vertexBuffer.getPrimitiveType(), firstVertex, vertexCount);
+
+ // Unbind vertex buffer
+ VertexBuffer::bind(NULL);
+
+ cleanupDraw(states);
// Update the cache
- m_cache.useVertexCache = useVertexCache;
+ m_cache.useVertexCache = false;
+ m_cache.texCoordsArrayEnabled = true;
}
}
////////////////////////////////////////////////////////////
+bool RenderTarget::setActive(bool active)
+{
+ // Mark this RenderTarget as active or no longer active in the tracking map
+ {
+ sf::Lock lock(mutex);
+
+ Uint64 contextId = Context::getActiveContextId();
+
+ ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(contextId);
+
+ if (active)
+ {
+ if (iter == contextRenderTargetMap.end())
+ {
+ contextRenderTargetMap[contextId] = m_id;
+
+ m_cache.enable = false;
+ }
+ else if (iter->second != m_id)
+ {
+ iter->second = m_id;
+
+ m_cache.enable = false;
+ }
+ }
+ else
+ {
+ if (iter != contextRenderTargetMap.end())
+ contextRenderTargetMap.erase(iter);
+
+ m_cache.enable = false;
+ }
+ }
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
void RenderTarget::pushGLStates()
{
- if (activate(true))
+ if (isActive(m_id) || setActive(true))
{
#ifdef SFML_DEBUG
// make sure that the user didn't leave an unchecked OpenGL error
@@ -336,7 +462,7 @@ void RenderTarget::pushGLStates()
////////////////////////////////////////////////////////////
void RenderTarget::popGLStates()
{
- if (activate(true))
+ if (isActive(m_id) || setActive(true))
{
glCheck(glMatrixMode(GL_PROJECTION));
glCheck(glPopMatrix());
@@ -357,8 +483,15 @@ void RenderTarget::resetGLStates()
{
// Check here to make sure a context change does not happen after activate(true)
bool shaderAvailable = Shader::isAvailable();
+ bool vertexBufferAvailable = VertexBuffer::isAvailable();
- if (activate(true))
+ // Workaround for states not being properly reset on
+ // macOS unless a context switch really takes place
+ #if defined(SFML_SYSTEM_MACOS)
+ setActive(false);
+ #endif
+
+ if (isActive(m_id) || setActive(true))
{
// Make sure that extensions are initialized
priv::ensureExtensionsInit();
@@ -378,6 +511,7 @@ void RenderTarget::resetGLStates()
glCheck(glEnable(GL_TEXTURE_2D));
glCheck(glEnable(GL_BLEND));
glCheck(glMatrixMode(GL_MODELVIEW));
+ glCheck(glLoadIdentity());
glCheck(glEnableClientState(GL_VERTEX_ARRAY));
glCheck(glEnableClientState(GL_COLOR_ARRAY));
glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
@@ -385,15 +519,21 @@ void RenderTarget::resetGLStates()
// Apply the default SFML states
applyBlendMode(BlendAlpha);
- applyTransform(Transform::Identity);
applyTexture(NULL);
if (shaderAvailable)
applyShader(NULL);
+ if (vertexBufferAvailable)
+ glCheck(VertexBuffer::bind(NULL));
+
+ m_cache.texCoordsArrayEnabled = true;
+
m_cache.useVertexCache = false;
// Set the default view
setView(getView());
+
+ m_cache.enable = true;
}
}
@@ -482,7 +622,10 @@ void RenderTarget::applyTransform(const Transform& transform)
{
// No need to call glMatrixMode(GL_MODELVIEW), it is always the
// current mode (for optimization purpose, since it's the most used)
- glCheck(glLoadMatrixf(transform.getMatrix()));
+ if (transform == Transform::Identity)
+ glCheck(glLoadIdentity());
+ else
+ glCheck(glLoadMatrixf(transform.getMatrix()));
}
@@ -501,6 +644,86 @@ void RenderTarget::applyShader(const Shader* shader)
Shader::bind(shader);
}
+
+////////////////////////////////////////////////////////////
+void RenderTarget::setupDraw(bool useVertexCache, const RenderStates& states)
+{
+ // First set the persistent OpenGL states if it's the very first call
+ if (!m_cache.glStatesSet)
+ resetGLStates();
+
+ if (useVertexCache)
+ {
+ // Since vertices are transformed, we must use an identity transform to render them
+ if (!m_cache.enable || !m_cache.useVertexCache)
+ glCheck(glLoadIdentity());
+ }
+ else
+ {
+ applyTransform(states.transform);
+ }
+
+ // Apply the view
+ if (!m_cache.enable || m_cache.viewChanged)
+ applyCurrentView();
+
+ // Apply the blend mode
+ if (!m_cache.enable || (states.blendMode != m_cache.lastBlendMode))
+ applyBlendMode(states.blendMode);
+
+ // Apply the texture
+ if (!m_cache.enable || (states.texture && states.texture->m_fboAttachment))
+ {
+ // If the texture is an FBO attachment, always rebind it
+ // in order to inform the OpenGL driver that we want changes
+ // made to it in other contexts to be visible here as well
+ // This saves us from having to call glFlush() in
+ // RenderTextureImplFBO which can be quite costly
+ // See: https://www.khronos.org/opengl/wiki/Memory_Model
+ applyTexture(states.texture);
+ }
+ else
+ {
+ Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
+ if (textureId != m_cache.lastTextureId)
+ applyTexture(states.texture);
+ }
+
+ // Apply the shader
+ if (states.shader)
+ applyShader(states.shader);
+}
+
+
+////////////////////////////////////////////////////////////
+void RenderTarget::drawPrimitives(PrimitiveType type, std::size_t firstVertex, std::size_t vertexCount)
+{
+ // Find the OpenGL primitive type
+ static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
+ GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
+ GLenum mode = modes[type];
+
+ // Draw the primitives
+ glCheck(glDrawArrays(mode, firstVertex, static_cast<GLsizei>(vertexCount)));
+}
+
+
+////////////////////////////////////////////////////////////
+void RenderTarget::cleanupDraw(const RenderStates& states)
+{
+ // Unbind the shader, if any
+ if (states.shader)
+ applyShader(NULL);
+
+ // If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture.
+ // This prevents a bug where some drivers do not clear RenderTextures properly.
+ if (states.texture && states.texture->m_fboAttachment)
+ applyTexture(NULL);
+
+ // Re-enable the cache at the end of the draw if it was disabled
+ m_cache.enable = true;
+}
+
} // namespace sf
diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp
index a84193e..0805627 100644
--- a/src/SFML/Graphics/RenderTexture.cpp
+++ b/src/SFML/Graphics/RenderTexture.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -51,6 +51,13 @@ RenderTexture::~RenderTexture()
////////////////////////////////////////////////////////////
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
{
+ return create(width, height, ContextSettings(depthBuffer ? 32 : 0));
+}
+
+
+////////////////////////////////////////////////////////////
+bool RenderTexture::create(unsigned int width, unsigned int height, const ContextSettings& settings)
+{
// Create the texture
if (!m_texture.create(width, height))
{
@@ -78,7 +85,7 @@ bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBu
}
// Initialize the render texture
- if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
+ if (!m_impl->create(width, height, m_texture.m_texture, settings))
return false;
// We can now initialize the render target part
@@ -89,6 +96,20 @@ bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBu
////////////////////////////////////////////////////////////
+unsigned int RenderTexture::getMaximumAntialiasingLevel()
+{
+ if (priv::RenderTextureImplFBO::isAvailable())
+ {
+ return priv::RenderTextureImplFBO::getMaximumAntialiasingLevel();
+ }
+ else
+ {
+ return priv::RenderTextureImplDefault::getMaximumAntialiasingLevel();
+ }
+}
+
+
+////////////////////////////////////////////////////////////
void RenderTexture::setSmooth(bool smooth)
{
m_texture.setSmooth(smooth);
@@ -126,7 +147,13 @@ bool RenderTexture::generateMipmap()
////////////////////////////////////////////////////////////
bool RenderTexture::setActive(bool active)
{
- return m_impl && m_impl->activate(active);
+ bool result = m_impl && m_impl->activate(active);
+
+ // Update RenderTarget tracking
+ if (result)
+ RenderTarget::setActive(active);
+
+ return result;
}
@@ -134,7 +161,7 @@ bool RenderTexture::setActive(bool active)
void RenderTexture::display()
{
// Update the target texture
- if (setActive(true))
+ if (priv::RenderTextureImplFBO::isAvailable() || setActive(true))
{
m_impl->updateTexture(m_texture.m_texture);
m_texture.m_pixelsFlipped = true;
@@ -156,11 +183,4 @@ const Texture& RenderTexture::getTexture() const
return m_texture;
}
-
-////////////////////////////////////////////////////////////
-bool RenderTexture::activate(bool active)
-{
- return setActive(active);
-}
-
} // namespace sf
diff --git a/src/SFML/Graphics/RenderTextureImpl.cpp b/src/SFML/Graphics/RenderTextureImpl.cpp
index 19023b3..d1e927c 100644
--- a/src/SFML/Graphics/RenderTextureImpl.cpp
+++ b/src/SFML/Graphics/RenderTextureImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/RenderTextureImpl.hpp b/src/SFML/Graphics/RenderTextureImpl.hpp
index e2fece0..5a357c7 100644
--- a/src/SFML/Graphics/RenderTextureImpl.hpp
+++ b/src/SFML/Graphics/RenderTextureImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -33,6 +33,9 @@
namespace sf
{
+
+struct ContextSettings;
+
namespace priv
{
////////////////////////////////////////////////////////////
@@ -52,15 +55,15 @@ public:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
- /// \param width Width of the texture to render to
- /// \param height Height of the texture to render to
- /// \param textureId OpenGL identifier of the target texture
- /// \param depthBuffer Is a depth buffer requested?
+ /// \param width Width of the texture to render to
+ /// \param height Height of the texture to render to
+ /// \param textureId OpenGL identifier of the target texture
+ /// \param settings Context settings to create render-texture with
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
- virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
+ virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings) = 0;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
diff --git a/src/SFML/Graphics/RenderTextureImplDefault.cpp b/src/SFML/Graphics/RenderTextureImplDefault.cpp
index c52679d..29399d5 100644
--- a/src/SFML/Graphics/RenderTextureImplDefault.cpp
+++ b/src/SFML/Graphics/RenderTextureImplDefault.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -55,14 +55,24 @@ RenderTextureImplDefault::~RenderTextureImplDefault()
////////////////////////////////////////////////////////////
-bool RenderTextureImplDefault::create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
+unsigned int RenderTextureImplDefault::getMaximumAntialiasingLevel()
+{
+ // If the system is so old that it doesn't support FBOs, chances are it is
+ // also using either a software renderer or some CPU emulated support for AA
+ // In order to not cripple performance in this rare case, we just return 0 here
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////
+bool RenderTextureImplDefault::create(unsigned int width, unsigned int height, unsigned int, const ContextSettings& settings)
{
// Store the dimensions
m_width = width;
m_height = height;
// Create the in-memory OpenGL context
- m_context = new Context(ContextSettings(depthBuffer ? 32 : 0), width, height);
+ m_context = new Context(settings, width, height);
return true;
}
diff --git a/src/SFML/Graphics/RenderTextureImplDefault.hpp b/src/SFML/Graphics/RenderTextureImplDefault.hpp
index 803b18f..c3b59ae 100644
--- a/src/SFML/Graphics/RenderTextureImplDefault.hpp
+++ b/src/SFML/Graphics/RenderTextureImplDefault.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -58,20 +58,28 @@ public:
////////////////////////////////////////////////////////////
~RenderTextureImplDefault();
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the maximum anti-aliasing level supported by the system
+ ///
+ /// \return The maximum anti-aliasing level supported by the system
+ ///
+ ////////////////////////////////////////////////////////////
+ static unsigned int getMaximumAntialiasingLevel();
+
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
- /// \param width Width of the texture to render to
- /// \param height Height of the texture to render to
- /// \param textureId OpenGL identifier of the target texture
- /// \param depthBuffer Is a depth buffer requested?
+ /// \param width Width of the texture to render to
+ /// \param height Height of the texture to render to
+ /// \param textureId OpenGL identifier of the target texture
+ /// \param settings Context settings to create render-texture with
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
- virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
+ virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp
index 58dcb46..301aa04 100644
--- a/src/SFML/Graphics/RenderTextureImplFBO.cpp
+++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -28,7 +28,67 @@
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
+#include <SFML/System/Mutex.hpp>
+#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
+#include <utility>
+#include <set>
+
+
+namespace
+{
+ // Set to track all active FBO mappings
+ // This is used to free active FBOs while their owning
+ // RenderTextureImplFBO is still alive
+ std::set<std::map<sf::Uint64, unsigned int>*> frameBuffers;
+
+ // Set to track all stale FBOs
+ // This is used to free stale FBOs after their owning
+ // RenderTextureImplFBO has already been destroyed
+ // An FBO cannot be destroyed until it's containing context
+ // becomes active, so the destruction of the RenderTextureImplFBO
+ // has to be decoupled from the destruction of the FBOs themselves
+ std::set<std::pair<sf::Uint64, unsigned int> > staleFrameBuffers;
+
+ // Mutex to protect both active and stale frame buffer sets
+ sf::Mutex mutex;
+
+ // Callback that is called every time a context is destroyed
+ void contextDestroyCallback(void* arg)
+ {
+ sf::Lock lock(mutex);
+
+ sf::Uint64 contextId = sf::Context::getActiveContextId();
+
+ // Destroy active frame buffer objects
+ for (std::set<std::map<sf::Uint64, unsigned int>*>::iterator frameBuffersIter = frameBuffers.begin(); frameBuffersIter != frameBuffers.end(); ++frameBuffersIter)
+ {
+ for (std::map<sf::Uint64, unsigned int>::iterator iter = (*frameBuffersIter)->begin(); iter != (*frameBuffersIter)->end(); ++iter)
+ {
+ if (iter->first == contextId)
+ {
+ GLuint frameBuffer = static_cast<GLuint>(iter->second);
+ glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
+
+ // Erase the entry from the RenderTextureImplFBO's map
+ (*frameBuffersIter)->erase(iter);
+
+ break;
+ }
+ }
+ }
+
+ // Destroy stale frame buffer objects
+ for (std::set<std::pair<sf::Uint64, unsigned int> >::iterator iter = staleFrameBuffers.begin(); iter != staleFrameBuffers.end(); ++iter)
+ {
+ if (iter->first == contextId)
+ {
+ GLuint frameBuffer = static_cast<GLuint>(iter->second);
+ glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
+ }
+ }
+ }
+}
namespace sf
@@ -37,34 +97,62 @@ namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImplFBO::RenderTextureImplFBO() :
-m_context (NULL),
-m_frameBuffer(0),
-m_depthBuffer(0)
+m_depthStencilBuffer(0),
+m_colorBuffer (0),
+m_width (0),
+m_height (0),
+m_context (NULL),
+m_textureId (0),
+m_multisample (false),
+m_stencil (false)
{
+ Lock lock(mutex);
+
+ // Register the context destruction callback
+ registerContextDestroyCallback(contextDestroyCallback, 0);
+ // Insert the new frame buffer mapping into the set of all active mappings
+ frameBuffers.insert(&m_frameBuffers);
+ frameBuffers.insert(&m_multisampleFrameBuffers);
}
////////////////////////////////////////////////////////////
RenderTextureImplFBO::~RenderTextureImplFBO()
{
- m_context->setActive(true);
+ TransientContextLock contextLock;
+
+ Lock lock(mutex);
- // Destroy the depth buffer
- if (m_depthBuffer)
+ // Remove the frame buffer mapping from the set of all active mappings
+ frameBuffers.erase(&m_frameBuffers);
+ frameBuffers.erase(&m_multisampleFrameBuffers);
+
+ // Destroy the color buffer
+ if (m_colorBuffer)
{
- GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
- glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
+ GLuint colorBuffer = static_cast<GLuint>(m_colorBuffer);
+ glCheck(GLEXT_glDeleteRenderbuffers(1, &colorBuffer));
}
- // Destroy the frame buffer
- if (m_frameBuffer)
+ // Destroy the depth/stencil buffer
+ if (m_depthStencilBuffer)
{
- GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer);
- glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
+ GLuint depthStencilBuffer = static_cast<GLuint>(m_depthStencilBuffer);
+ glCheck(GLEXT_glDeleteRenderbuffers(1, &depthStencilBuffer));
}
- // Delete the context
+ // Move all frame buffer objects to stale set
+ for (std::map<Uint64, unsigned int>::iterator iter = m_frameBuffers.begin(); iter != m_frameBuffers.end(); ++iter)
+ staleFrameBuffers.insert(std::make_pair(iter->first, iter->second));
+
+ for (std::map<Uint64, unsigned int>::iterator iter = m_multisampleFrameBuffers.begin(); iter != m_multisampleFrameBuffers.end(); ++iter)
+ staleFrameBuffers.insert(std::make_pair(iter->first, iter->second));
+
+ // Clean up FBOs
+ contextDestroyCallback(0);
+
+ // Delete the backup context if we had to create one
delete m_context;
}
@@ -82,40 +170,247 @@ bool RenderTextureImplFBO::isAvailable()
////////////////////////////////////////////////////////////
-bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
+unsigned int RenderTextureImplFBO::getMaximumAntialiasingLevel()
{
- // Create the context
- m_context = new Context;
+ TransientContextLock lock;
+
+ GLint samples = 0;
+
+#ifndef SFML_OPENGL_ES
+
+ glCheck(glGetIntegerv(GLEXT_GL_MAX_SAMPLES, &samples));
+
+#endif
+
+ return static_cast<unsigned int>(samples);
+}
+
+
+////////////////////////////////////////////////////////////
+void RenderTextureImplFBO::unbind()
+{
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
+}
+
+
+////////////////////////////////////////////////////////////
+bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings)
+{
+ // Store the dimensions
+ m_width = width;
+ m_height = height;
+
+ {
+ TransientContextLock lock;
+ // Make sure that extensions are initialized
+ priv::ensureExtensionsInit();
+
+ if (settings.antialiasingLevel && !(GLEXT_framebuffer_multisample && GLEXT_framebuffer_blit))
+ return false;
+
+ if (settings.stencilBits && !GLEXT_packed_depth_stencil)
+ return false;
+
+#ifndef SFML_OPENGL_ES
+
+ // Check if the requested anti-aliasing level is supported
+ if (settings.antialiasingLevel)
+ {
+ GLint samples = 0;
+ glCheck(glGetIntegerv(GLEXT_GL_MAX_SAMPLES, &samples));
+
+ if (settings.antialiasingLevel > static_cast<unsigned int>(samples))
+ {
+ err() << "Impossible to create render texture (unsupported anti-aliasing level)";
+ err() << " Requested: " << settings.antialiasingLevel << " Maximum supported: " << samples << std::endl;
+ return false;
+ }
+ }
+
+#endif
+
+
+ if (!settings.antialiasingLevel)
+ {
+ // Create the depth/stencil buffer if requested
+ if (settings.stencilBits)
+ {
+
+#ifndef SFML_OPENGL_ES
+
+ GLuint depthStencil = 0;
+ glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
+ m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
+ if (!m_depthStencilBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the attached depth/stencil buffer)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+ glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH24_STENCIL8, width, height));
+
+#else
+
+ err() << "Impossible to create render texture (failed to create the attached depth/stencil buffer)" << std::endl;
+ return false;
+
+#endif // SFML_OPENGL_ES
+
+ m_stencil = true;
+
+ }
+ else if (settings.depthBits)
+ {
+ GLuint depthStencil = 0;
+ glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
+ m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
+ if (!m_depthStencilBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+ glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
+ }
+ }
+ else
+ {
+
+#ifndef SFML_OPENGL_ES
+
+ // Create the multisample color buffer
+ GLuint color = 0;
+ glCheck(GLEXT_glGenRenderbuffers(1, &color));
+ m_colorBuffer = static_cast<unsigned int>(color);
+ if (!m_colorBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the attached multisample color buffer)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_colorBuffer));
+ glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GL_RGBA, width, height));
+
+ // Create the multisample depth/stencil buffer if requested
+ if (settings.stencilBits)
+ {
+ GLuint depthStencil = 0;
+ glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
+ m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
+ if (!m_depthStencilBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the attached multisample depth/stencil buffer)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+ glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GLEXT_GL_DEPTH24_STENCIL8, width, height));
+
+ m_stencil = true;
+ }
+ else if (settings.depthBits)
+ {
+ GLuint depthStencil = 0;
+ glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
+ m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
+ if (!m_depthStencilBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the attached multisample depth buffer)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+ glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GLEXT_GL_DEPTH_COMPONENT, width, height));
+ }
+
+#else
+
+ err() << "Impossible to create render texture (failed to create the multisample render buffers)" << std::endl;
+ return false;
+
+#endif // SFML_OPENGL_ES
+
+ m_multisample = true;
+
+ }
+ }
+
+ // Save our texture ID in order to be able to attach it to an FBO at any time
+ m_textureId = textureId;
+
+ // We can't create an FBO now if there is no active context
+ if (!Context::getActiveContextId())
+ return true;
+
+#ifndef SFML_OPENGL_ES
+
+ // Save the current bindings so we can restore them after we are done
+ GLint readFramebuffer = 0;
+ GLint drawFramebuffer = 0;
+
+ glCheck(glGetIntegerv(GLEXT_GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer));
+ glCheck(glGetIntegerv(GLEXT_GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer));
+
+ if (createFrameBuffer())
+ {
+ // Restore previously bound framebuffers
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, readFramebuffer));
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, drawFramebuffer));
+
+ return true;
+ }
+
+#else
+
+ // Save the current binding so we can restore them after we are done
+ GLint frameBuffer = 0;
+
+ glCheck(glGetIntegerv(GLEXT_GL_FRAMEBUFFER_BINDING, &frameBuffer));
+
+ if (createFrameBuffer())
+ {
+ // Restore previously bound framebuffer
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, frameBuffer));
+
+ return true;
+ }
+
+#endif
+
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool RenderTextureImplFBO::createFrameBuffer()
+{
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
- m_frameBuffer = static_cast<unsigned int>(frameBuffer);
- if (!m_frameBuffer)
+
+ if (!frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false;
}
- glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, frameBuffer));
- // Create the depth buffer if requested
- if (depthBuffer)
+ // Link the depth/stencil renderbuffer to the frame buffer
+ if (!m_multisample && m_depthStencilBuffer)
{
- GLuint depth = 0;
- glCheck(GLEXT_glGenRenderbuffers(1, &depth));
- m_depthBuffer = static_cast<unsigned int>(depth);
- if (!m_depthBuffer)
+ glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+
+#ifndef SFML_OPENGL_ES
+
+ if (m_stencil)
{
- err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
- return false;
+ glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_STENCIL_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
}
- glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
- glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
- glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
+
+#endif
+
}
// Link the texture to the frame buffer
- glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
+ glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureId, 0));
// A final check, just to be sure...
GLenum status;
@@ -123,10 +418,68 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
+ glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
return false;
}
+ {
+ Lock lock(mutex);
+
+ // Insert the FBO into our map
+ m_frameBuffers.insert(std::make_pair(Context::getActiveContextId(), static_cast<unsigned int>(frameBuffer)));
+ }
+
+#ifndef SFML_OPENGL_ES
+
+ if (m_multisample)
+ {
+ // Create the multisample framebuffer object
+ GLuint multisampleFrameBuffer = 0;
+ glCheck(GLEXT_glGenFramebuffers(1, &multisampleFrameBuffer));
+
+ if (!multisampleFrameBuffer)
+ {
+ err() << "Impossible to create render texture (failed to create the multisample frame buffer object)" << std::endl;
+ return false;
+ }
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, multisampleFrameBuffer));
+
+ // Link the multisample color buffer to the frame buffer
+ glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_colorBuffer));
+ glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GLEXT_GL_RENDERBUFFER, m_colorBuffer));
+
+ // Link the depth/stencil renderbuffer to the frame buffer
+ if (m_depthStencilBuffer)
+ {
+ glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+
+ if (m_stencil)
+ {
+ glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_STENCIL_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
+ }
+ }
+
+ // A final check, just to be sure...
+ glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
+ if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
+ {
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
+ glCheck(GLEXT_glDeleteFramebuffers(1, &multisampleFrameBuffer));
+ err() << "Impossible to create render texture (failed to link the render buffers to the multisample frame buffer)" << std::endl;
+ return false;
+ }
+
+ {
+ Lock lock(mutex);
+
+ // Insert the FBO into our map
+ m_multisampleFrameBuffers.insert(std::make_pair(Context::getActiveContextId(), static_cast<unsigned int>(multisampleFrameBuffer)));
+ }
+ }
+
+#endif
+
return true;
}
@@ -134,14 +487,101 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::activate(bool active)
{
- return m_context->setActive(active);
+ // Unbind the FBO if requested
+ if (!active)
+ {
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
+ return true;
+ }
+
+ Uint64 contextId = Context::getActiveContextId();
+
+ // In the odd case we have to activate and there is no active
+ // context yet, we have to create one
+ if (!contextId)
+ {
+ if (!m_context)
+ m_context = new Context;
+
+ m_context->setActive(true);
+
+ contextId = Context::getActiveContextId();
+
+ if (!contextId)
+ {
+ err() << "Impossible to activate render texture (failed to create backup context)" << std::endl;
+
+ return false;
+ }
+ }
+
+ // Lookup the FBO corresponding to the currently active context
+ // If none is found, there is no FBO corresponding to the
+ // currently active context so we will have to create a new FBO
+ {
+ Lock lock(mutex);
+
+ std::map<Uint64, unsigned int>::iterator iter;
+
+ if (m_multisample)
+ {
+ iter = m_multisampleFrameBuffers.find(contextId);
+
+ if (iter != m_multisampleFrameBuffers.end())
+ {
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, iter->second));
+
+ return true;
+ }
+ }
+ else
+ {
+ iter = m_frameBuffers.find(contextId);
+
+ if (iter != m_frameBuffers.end())
+ {
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, iter->second));
+
+ return true;
+ }
+ }
+ }
+
+ return createFrameBuffer();
}
////////////////////////////////////////////////////////////
void RenderTextureImplFBO::updateTexture(unsigned int)
{
- glCheck(glFlush());
+ // If multisampling is enabled, we need to resolve by blitting
+ // from our FBO with multisample renderbuffer attachments
+ // to our FBO to which our target texture is attached
+
+#ifndef SFML_OPENGL_ES
+
+ // In case of multisampling, make sure both FBOs
+ // are already available within the current context
+ if (m_multisample && m_width && m_height && activate(true))
+ {
+ Uint64 contextId = Context::getActiveContextId();
+
+ Lock lock(mutex);
+
+ std::map<Uint64, unsigned int>::iterator iter = m_frameBuffers.find(contextId);
+ std::map<Uint64, unsigned int>::iterator multisampleIter = m_multisampleFrameBuffers.find(contextId);
+
+ if ((iter != m_frameBuffers.end()) && (multisampleIter != m_multisampleFrameBuffers.end()))
+ {
+ // Set up the blit target (draw framebuffer) and blit (from the read framebuffer, our multisample FBO)
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, iter->second));
+ glCheck(GLEXT_glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, multisampleIter->second));
+ }
+ }
+
+#endif // SFML_OPENGL_ES
+
}
} // namespace priv
diff --git a/src/SFML/Graphics/RenderTextureImplFBO.hpp b/src/SFML/Graphics/RenderTextureImplFBO.hpp
index c987281..f83074e 100644
--- a/src/SFML/Graphics/RenderTextureImplFBO.hpp
+++ b/src/SFML/Graphics/RenderTextureImplFBO.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,7 @@
#include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp>
+#include <map>
namespace sf
@@ -66,20 +67,42 @@ public:
////////////////////////////////////////////////////////////
static bool isAvailable();
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the maximum anti-aliasing level supported by the system
+ ///
+ /// \return The maximum anti-aliasing level supported by the system
+ ///
+ ////////////////////////////////////////////////////////////
+ static unsigned int getMaximumAntialiasingLevel();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Unbind the currently bound FBO
+ ///
+ ////////////////////////////////////////////////////////////
+ static void unbind();
+
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
- /// \param width Width of the texture to render to
- /// \param height Height of the texture to render to
- /// \param textureId OpenGL identifier of the target texture
- /// \param depthBuffer Is a depth buffer requested?
+ /// \param width Width of the texture to render to
+ /// \param height Height of the texture to render to
+ /// \param textureId OpenGL identifier of the target texture
+ /// \param settings Context settings to create render-texture with
+ ///
+ /// \return True if creation has been successful
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create an FBO in the current context
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
- virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
+ bool createFrameBuffer();
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
@@ -102,9 +125,16 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
- unsigned int m_frameBuffer; ///< OpenGL frame buffer object
- unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
+ std::map<Uint64, unsigned int> m_frameBuffers; ///< OpenGL frame buffer objects per context
+ std::map<Uint64, unsigned int> m_multisampleFrameBuffers; ///< Optional per-context OpenGL frame buffer objects with multisample attachments
+ unsigned int m_depthStencilBuffer; ///< Optional depth/stencil buffer attached to the frame buffer
+ unsigned int m_colorBuffer; ///< Optional multisample color buffer attached to the frame buffer
+ unsigned int m_width; ///< Width of the attachments
+ unsigned int m_height; ///< Height of the attachments
+ Context* m_context; ///< Backup OpenGL context, used when none already exist
+ unsigned int m_textureId; ///< The ID of the texture to attach to the FBO
+ bool m_multisample; ///< Whether we have to create a multisample frame buffer as well
+ bool m_stencil; ///< Whether we have stencil attachment
};
} // namespace priv
diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp
index 7ac7804..906363b 100644
--- a/src/SFML/Graphics/RenderWindow.cpp
+++ b/src/SFML/Graphics/RenderWindow.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -27,6 +27,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Texture.hpp>
+#include <SFML/Graphics/GLCheck.hpp>
+#include <SFML/Graphics/RenderTextureImplFBO.hpp>
namespace sf
@@ -62,16 +64,31 @@ RenderWindow::~RenderWindow()
////////////////////////////////////////////////////////////
-bool RenderWindow::activate(bool active)
+Vector2u RenderWindow::getSize() const
{
- return setActive(active);
+ return Window::getSize();
}
////////////////////////////////////////////////////////////
-Vector2u RenderWindow::getSize() const
+bool RenderWindow::setActive(bool active)
{
- return Window::getSize();
+ bool result = Window::setActive(active);
+
+ // Update RenderTarget tracking
+ if (result)
+ RenderTarget::setActive(active);
+
+ // If FBOs are available, make sure none are bound when we
+ // try to draw to the default framebuffer of the RenderWindow
+ if (result && priv::RenderTextureImplFBO::isAvailable())
+ {
+ priv::RenderTextureImplFBO::unbind();
+
+ return true;
+ }
+
+ return result;
}
diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp
index 92b92db..353a72d 100644
--- a/src/SFML/Graphics/Shader.cpp
+++ b/src/SFML/Graphics/Shader.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -593,7 +593,7 @@ void Shader::setUniformArray(const std::string& name, const float* scalarArray,
{
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniform1fv(binder.location, length, scalarArray));
+ glCheck(GLEXT_glUniform1fv(binder.location, static_cast<GLsizei>(length), scalarArray));
}
@@ -604,7 +604,7 @@ void Shader::setUniformArray(const std::string& name, const Glsl::Vec2* vectorAr
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniform2fv(binder.location, length, &contiguous[0]));
+ glCheck(GLEXT_glUniform2fv(binder.location, static_cast<GLsizei>(length), &contiguous[0]));
}
@@ -615,7 +615,7 @@ void Shader::setUniformArray(const std::string& name, const Glsl::Vec3* vectorAr
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniform3fv(binder.location, length, &contiguous[0]));
+ glCheck(GLEXT_glUniform3fv(binder.location, static_cast<GLsizei>(length), &contiguous[0]));
}
@@ -626,7 +626,7 @@ void Shader::setUniformArray(const std::string& name, const Glsl::Vec4* vectorAr
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniform4fv(binder.location, length, &contiguous[0]));
+ glCheck(GLEXT_glUniform4fv(binder.location, static_cast<GLsizei>(length), &contiguous[0]));
}
@@ -641,7 +641,7 @@ void Shader::setUniformArray(const std::string& name, const Glsl::Mat3* matrixAr
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniformMatrix3fv(binder.location, length, GL_FALSE, &contiguous[0]));
+ glCheck(GLEXT_glUniformMatrix3fv(binder.location, static_cast<GLsizei>(length), GL_FALSE, &contiguous[0]));
}
@@ -656,7 +656,7 @@ void Shader::setUniformArray(const std::string& name, const Glsl::Mat4* matrixAr
UniformBinder binder(*this, name);
if (binder.location != -1)
- glCheck(GLEXT_glUniformMatrix4fv(binder.location, length, GL_FALSE, &contiguous[0]));
+ glCheck(GLEXT_glUniformMatrix4fv(binder.location, static_cast<GLsizei>(length), GL_FALSE, &contiguous[0]));
}
diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp
index c0d4f82..545b6fa 100644
--- a/src/SFML/Graphics/Shape.cpp
+++ b/src/SFML/Graphics/Shape.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -251,6 +251,14 @@ void Shape::updateTexCoords()
////////////////////////////////////////////////////////////
void Shape::updateOutline()
{
+ // Return if there is no outline
+ if (m_outlineThickness == 0.f)
+ {
+ m_outlineVertices.clear();
+ m_bounds = m_insideBounds;
+ return;
+ }
+
std::size_t count = m_vertices.getVertexCount() - 2;
m_outlineVertices.resize((count + 1) * 2);
diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp
index 71d5c70..feb79a4 100644
--- a/src/SFML/Graphics/Sprite.cpp
+++ b/src/SFML/Graphics/Sprite.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp
index 5ad50c1..3773616 100644
--- a/src/SFML/Graphics/Text.cpp
+++ b/src/SFML/Graphics/Text.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -48,7 +48,7 @@ namespace
}
// Add a glyph quad to the vertex array
- void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italic, float outlineThickness = 0)
+ void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear, float outlineThickness = 0)
{
float left = glyph.bounds.left;
float top = glyph.bounds.top;
@@ -60,12 +60,12 @@ namespace
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
- vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italic * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u1, v1)));
- vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italic * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
- vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italic * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
- vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italic * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
- vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italic * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
- vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italic * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u2, v2)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u1, v1)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
+ vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u2, v2)));
}
}
@@ -74,17 +74,20 @@ namespace sf
{
////////////////////////////////////////////////////////////
Text::Text() :
-m_string (),
-m_font (NULL),
-m_characterSize (30),
-m_style (Regular),
-m_fillColor (255, 255, 255),
-m_outlineColor (0, 0, 0),
-m_outlineThickness (0),
-m_vertices (Triangles),
-m_outlineVertices (Triangles),
-m_bounds (),
-m_geometryNeedUpdate(false)
+m_string (),
+m_font (NULL),
+m_characterSize (30),
+m_letterSpacingFactor(1.f),
+m_lineSpacingFactor (1.f),
+m_style (Regular),
+m_fillColor (255, 255, 255),
+m_outlineColor (0, 0, 0),
+m_outlineThickness (0),
+m_vertices (Triangles),
+m_outlineVertices (Triangles),
+m_bounds (),
+m_geometryNeedUpdate (false),
+m_fontTextureId (0)
{
}
@@ -92,17 +95,20 @@ m_geometryNeedUpdate(false)
////////////////////////////////////////////////////////////
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
-m_string (string),
-m_font (&font),
-m_characterSize (characterSize),
-m_style (Regular),
-m_fillColor (255, 255, 255),
-m_outlineColor (0, 0, 0),
-m_outlineThickness (0),
-m_vertices (Triangles),
-m_outlineVertices (Triangles),
-m_bounds (),
-m_geometryNeedUpdate(true)
+m_string (string),
+m_font (&font),
+m_characterSize (characterSize),
+m_letterSpacingFactor(1.f),
+m_lineSpacingFactor (1.f),
+m_style (Regular),
+m_fillColor (255, 255, 255),
+m_outlineColor (0, 0, 0),
+m_outlineThickness (0),
+m_vertices (Triangles),
+m_outlineVertices (Triangles),
+m_bounds (),
+m_geometryNeedUpdate (true),
+m_fontTextureId (0)
{
}
@@ -142,6 +148,28 @@ void Text::setCharacterSize(unsigned int size)
////////////////////////////////////////////////////////////
+void Text::setLetterSpacing(float spacingFactor)
+{
+ if (m_letterSpacingFactor != spacingFactor)
+ {
+ m_letterSpacingFactor = spacingFactor;
+ m_geometryNeedUpdate = true;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void Text::setLineSpacing(float spacingFactor)
+{
+ if (m_lineSpacingFactor != spacingFactor)
+ {
+ m_lineSpacingFactor = spacingFactor;
+ m_geometryNeedUpdate = true;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
void Text::setStyle(Uint32 style)
{
if (m_style != style)
@@ -228,6 +256,20 @@ unsigned int Text::getCharacterSize() const
////////////////////////////////////////////////////////////
+float Text::getLetterSpacing() const
+{
+ return m_letterSpacingFactor;
+}
+
+
+////////////////////////////////////////////////////////////
+float Text::getLineSpacing() const
+{
+ return m_lineSpacingFactor;
+}
+
+
+////////////////////////////////////////////////////////////
Uint32 Text::getStyle() const
{
return m_style;
@@ -274,9 +316,11 @@ Vector2f Text::findCharacterPos(std::size_t index) const
index = m_string.getSize();
// Precompute the variables needed by the algorithm
- bool bold = (m_style & Bold) != 0;
- float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
- float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
+ bool isBold = m_style & Bold;
+ float whitespaceWidth = m_font->getGlyph(L' ', m_characterSize, isBold).advance;
+ float letterSpacing = ( whitespaceWidth / 3.f ) * ( m_letterSpacingFactor - 1.f );
+ whitespaceWidth += letterSpacing;
+ float lineSpacing = m_font->getLineSpacing(m_characterSize) * m_lineSpacingFactor;
// Compute the position
Vector2f position;
@@ -286,19 +330,19 @@ Vector2f Text::findCharacterPos(std::size_t index) const
Uint32 curChar = m_string[i];
// Apply the kerning offset
- position.x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
+ position.x += m_font->getKerning(prevChar, curChar, m_characterSize);
prevChar = curChar;
// Handle special characters
switch (curChar)
{
- case ' ': position.x += hspace; continue;
- case '\t': position.x += hspace * 4; continue;
- case '\n': position.y += vspace; position.x = 0; continue;
+ case ' ': position.x += whitespaceWidth; continue;
+ case '\t': position.x += whitespaceWidth * 4; continue;
+ case '\n': position.y += lineSpacing; position.x = 0; continue;
}
// For regular characters, add the advance offset of the glyph
- position.x += static_cast<float>(m_font->getGlyph(curChar, m_characterSize, bold).advance);
+ position.x += m_font->getGlyph(curChar, m_characterSize, isBold).advance + letterSpacing;
}
// Transform the position to global coordinates
@@ -346,10 +390,16 @@ void Text::draw(RenderTarget& target, RenderStates states) const
////////////////////////////////////////////////////////////
void Text::ensureGeometryUpdate() const
{
- // Do nothing, if geometry has not changed
- if (!m_geometryNeedUpdate)
+ if (!m_font)
return;
+ // Do nothing, if geometry has not changed and the font texture has not changed
+ if (!m_geometryNeedUpdate && m_font->getTexture(m_characterSize).m_cacheId == m_fontTextureId)
+ return;
+
+ // Save the current fonts texture id
+ m_fontTextureId = m_font->getTexture(m_characterSize).m_cacheId;
+
// Mark geometry as updated
m_geometryNeedUpdate = false;
@@ -358,29 +408,31 @@ void Text::ensureGeometryUpdate() const
m_outlineVertices.clear();
m_bounds = FloatRect();
- // No font or text: nothing to draw
- if (!m_font || m_string.isEmpty())
+ // No text: nothing to draw
+ if (m_string.isEmpty())
return;
// Compute values related to the text style
- bool bold = (m_style & Bold) != 0;
- bool underlined = (m_style & Underlined) != 0;
- bool strikeThrough = (m_style & StrikeThrough) != 0;
- float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees
+ bool isBold = m_style & Bold;
+ bool isUnderlined = m_style & Underlined;
+ bool isStrikeThrough = m_style & StrikeThrough;
+ float italicShear = (m_style & Italic) ? 0.209f : 0.f; // 12 degrees in radians
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
// Compute the location of the strike through dynamically
// We use the center point of the lowercase 'x' glyph as the reference
// We reuse the underline thickness as the thickness of the strike through as well
- FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds;
+ FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, isBold).bounds;
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
// Precompute the variables needed by the algorithm
- float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
- float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
- float x = 0.f;
- float y = static_cast<float>(m_characterSize);
+ float whitespaceWidth = m_font->getGlyph(L' ', m_characterSize, isBold).advance;
+ float letterSpacing = ( whitespaceWidth / 3.f ) * ( m_letterSpacingFactor - 1.f );
+ whitespaceWidth += letterSpacing;
+ float lineSpacing = m_font->getLineSpacing(m_characterSize) * m_lineSpacingFactor;
+ float x = 0.f;
+ float y = static_cast<float>(m_characterSize);
// Create one quad for each character
float minX = static_cast<float>(m_characterSize);
@@ -397,7 +449,7 @@ void Text::ensureGeometryUpdate() const
prevChar = curChar;
// If we're using the underlined style and there's a new line, draw a line
- if (underlined && (curChar == L'\n'))
+ if (isUnderlined && (curChar == L'\n'))
{
addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness);
@@ -406,7 +458,7 @@ void Text::ensureGeometryUpdate() const
}
// If we're using the strike through style and there's a new line, draw a line across all characters
- if (strikeThrough && (curChar == L'\n'))
+ if (isStrikeThrough && (curChar == L'\n'))
{
addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness);
@@ -415,7 +467,7 @@ void Text::ensureGeometryUpdate() const
}
// Handle special characters
- if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n'))
+ if ((curChar == L' ') || (curChar == L'\n') || (curChar == L'\t'))
{
// Update the current bounds (min coordinates)
minX = std::min(minX, x);
@@ -423,9 +475,9 @@ void Text::ensureGeometryUpdate() const
switch (curChar)
{
- case ' ': x += hspace; break;
- case '\t': x += hspace * 4; break;
- case '\n': y += vspace; x = 0; break;
+ case L' ': x += whitespaceWidth; break;
+ case L'\t': x += whitespaceWidth * 4; break;
+ case L'\n': y += lineSpacing; x = 0; break;
}
// Update the current bounds (max coordinates)
@@ -436,11 +488,10 @@ void Text::ensureGeometryUpdate() const
continue;
}
-
// Apply the outline
if (m_outlineThickness != 0)
{
- const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold, m_outlineThickness);
+ const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold, m_outlineThickness);
float left = glyph.bounds.left;
float top = glyph.bounds.top;
@@ -448,20 +499,20 @@ void Text::ensureGeometryUpdate() const
float bottom = glyph.bounds.top + glyph.bounds.height;
// Add the outline glyph to the vertices
- addGlyphQuad(m_outlineVertices, Vector2f(x, y), m_outlineColor, glyph, italic, m_outlineThickness);
+ addGlyphQuad(m_outlineVertices, Vector2f(x, y), m_outlineColor, glyph, italicShear, m_outlineThickness);
// Update the current bounds with the outlined glyph bounds
- minX = std::min(minX, x + left - italic * bottom - m_outlineThickness);
- maxX = std::max(maxX, x + right - italic * top - m_outlineThickness);
+ minX = std::min(minX, x + left - italicShear * bottom - m_outlineThickness);
+ maxX = std::max(maxX, x + right - italicShear * top - m_outlineThickness);
minY = std::min(minY, y + top - m_outlineThickness);
maxY = std::max(maxY, y + bottom - m_outlineThickness);
}
// Extract the current glyph's description
- const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold);
+ const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold);
// Add the glyph to the vertices
- addGlyphQuad(m_vertices, Vector2f(x, y), m_fillColor, glyph, italic);
+ addGlyphQuad(m_vertices, Vector2f(x, y), m_fillColor, glyph, italicShear);
// Update the current bounds with the non outlined glyph bounds
if (m_outlineThickness == 0)
@@ -471,18 +522,18 @@ void Text::ensureGeometryUpdate() const
float right = glyph.bounds.left + glyph.bounds.width;
float bottom = glyph.bounds.top + glyph.bounds.height;
- minX = std::min(minX, x + left - italic * bottom);
- maxX = std::max(maxX, x + right - italic * top);
+ minX = std::min(minX, x + left - italicShear * bottom);
+ maxX = std::max(maxX, x + right - italicShear * top);
minY = std::min(minY, y + top);
maxY = std::max(maxY, y + bottom);
}
// Advance to the next character
- x += glyph.advance;
+ x += glyph.advance + letterSpacing;
}
// If we're using the underlined style, add the last line
- if (underlined && (x > 0))
+ if (isUnderlined && (x > 0))
{
addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness);
@@ -491,7 +542,7 @@ void Text::ensureGeometryUpdate() const
}
// If we're using the strike through style, add the last line across all characters
- if (strikeThrough && (x > 0))
+ if (isStrikeThrough && (x > 0))
{
addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness);
diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp
index 0910559..faeef7d 100644
--- a/src/SFML/Graphics/Texture.cpp
+++ b/src/SFML/Graphics/Texture.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -88,7 +88,20 @@ m_hasMipmap (false),
m_cacheId (getUniqueId())
{
if (copy.m_texture)
- loadFromImage(copy.copyToImage());
+ {
+ if (create(copy.getSize().x, copy.getSize().y))
+ {
+ update(copy);
+
+ // Force an OpenGL flush, so that the texture will appear updated
+ // in all contexts immediately (solves problems in multi-threaded apps)
+ glCheck(glFlush());
+ }
+ else
+ {
+ err() << "Failed to copy texture, failed to create new texture" << std::endl;
+ }
+ }
}
@@ -423,6 +436,115 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
////////////////////////////////////////////////////////////
+void Texture::update(const Texture& texture)
+{
+ // Update the whole texture
+ update(texture, 0, 0);
+}
+
+
+////////////////////////////////////////////////////////////
+void Texture::update(const Texture& texture, unsigned int x, unsigned int y)
+{
+ assert(x + texture.m_size.x <= m_size.x);
+ assert(y + texture.m_size.y <= m_size.y);
+
+ if (!m_texture || !texture.m_texture)
+ return;
+
+#ifndef SFML_OPENGL_ES
+
+ {
+ TransientContextLock lock;
+
+ // Make sure that extensions are initialized
+ priv::ensureExtensionsInit();
+ }
+
+ if (GLEXT_framebuffer_object && GLEXT_framebuffer_blit)
+ {
+ TransientContextLock lock;
+
+ // Save the current bindings so we can restore them after we are done
+ GLint readFramebuffer = 0;
+ GLint drawFramebuffer = 0;
+
+ glCheck(glGetIntegerv(GLEXT_GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer));
+ glCheck(glGetIntegerv(GLEXT_GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer));
+
+ // Create the framebuffers
+ GLuint sourceFrameBuffer = 0;
+ GLuint destFrameBuffer = 0;
+ glCheck(GLEXT_glGenFramebuffers(1, &sourceFrameBuffer));
+ glCheck(GLEXT_glGenFramebuffers(1, &destFrameBuffer));
+
+ if (!sourceFrameBuffer || !destFrameBuffer)
+ {
+ err() << "Cannot copy texture, failed to create a frame buffer object" << std::endl;
+ return;
+ }
+
+ // Link the source texture to the source frame buffer
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, sourceFrameBuffer));
+ glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_READ_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_texture, 0));
+
+ // Link the destination texture to the destination frame buffer
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, destFrameBuffer));
+ glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_DRAW_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0));
+
+ // A final check, just to be sure...
+ GLenum sourceStatus;
+ glCheck(sourceStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_READ_FRAMEBUFFER));
+
+ GLenum destStatus;
+ glCheck(destStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_DRAW_FRAMEBUFFER));
+
+ if ((sourceStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE) && (destStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE))
+ {
+ // Blit the texture contents from the source to the destination texture
+ glCheck(GLEXT_glBlitFramebuffer(
+ 0, texture.m_pixelsFlipped ? texture.m_size.y : 0, texture.m_size.x, texture.m_pixelsFlipped ? 0 : texture.m_size.y, // Source rectangle, flip y if source is flipped
+ x, y, x + texture.m_size.x, y + texture.m_size.y, // Destination rectangle
+ GL_COLOR_BUFFER_BIT, GL_NEAREST
+ ));
+ }
+ else
+ {
+ err() << "Cannot copy texture, failed to link texture to frame buffer" << std::endl;
+ }
+
+ // Restore previously bound framebuffers
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, readFramebuffer));
+ glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, drawFramebuffer));
+
+ // Delete the framebuffers
+ glCheck(GLEXT_glDeleteFramebuffers(1, &sourceFrameBuffer));
+ glCheck(GLEXT_glDeleteFramebuffers(1, &destFrameBuffer));
+
+ // Make sure that the current texture binding will be preserved
+ priv::TextureSaver save;
+
+ // Set the parameters of this texture
+ glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
+ glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
+ m_hasMipmap = false;
+ m_pixelsFlipped = false;
+ m_cacheId = getUniqueId();
+
+ // Force an OpenGL flush, so that the texture data will appear updated
+ // in all contexts immediately (solves problems in multi-threaded apps)
+ glCheck(glFlush());
+
+ return;
+ }
+
+#endif // SFML_OPENGL_ES
+
+ update(texture.copyToImage(), x, y);
+}
+
+
+////////////////////////////////////////////////////////////
void Texture::update(const Image& image)
{
// Update the whole texture
@@ -695,21 +817,31 @@ Texture& Texture::operator =(const Texture& right)
{
Texture temp(right);
- std::swap(m_size, temp.m_size);
- std::swap(m_actualSize, temp.m_actualSize);
- std::swap(m_texture, temp.m_texture);
- std::swap(m_isSmooth, temp.m_isSmooth);
- std::swap(m_isRepeated, temp.m_isRepeated);
- std::swap(m_pixelsFlipped, temp.m_pixelsFlipped);
- std::swap(m_fboAttachment, temp.m_fboAttachment);
- std::swap(m_hasMipmap, temp.m_hasMipmap);
- m_cacheId = getUniqueId();
+ swap(temp);
return *this;
}
////////////////////////////////////////////////////////////
+void Texture::swap(Texture& right)
+{
+ std::swap(m_size, right.m_size);
+ std::swap(m_actualSize, right.m_actualSize);
+ std::swap(m_texture, right.m_texture);
+ std::swap(m_isSmooth, right.m_isSmooth);
+ std::swap(m_sRgb, right.m_sRgb);
+ std::swap(m_isRepeated, right.m_isRepeated);
+ std::swap(m_pixelsFlipped, right.m_pixelsFlipped);
+ std::swap(m_fboAttachment, right.m_fboAttachment);
+ std::swap(m_hasMipmap, right.m_hasMipmap);
+
+ m_cacheId = getUniqueId();
+ right.m_cacheId = getUniqueId();
+}
+
+
+////////////////////////////////////////////////////////////
unsigned int Texture::getNativeHandle() const
{
return m_texture;
diff --git a/src/SFML/Graphics/TextureSaver.cpp b/src/SFML/Graphics/TextureSaver.cpp
index 1a119b5..2b7d8af 100644
--- a/src/SFML/Graphics/TextureSaver.cpp
+++ b/src/SFML/Graphics/TextureSaver.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/TextureSaver.hpp b/src/SFML/Graphics/TextureSaver.hpp
index 467f611..170fe46 100644
--- a/src/SFML/Graphics/TextureSaver.hpp
+++ b/src/SFML/Graphics/TextureSaver.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Transform.cpp b/src/SFML/Graphics/Transform.cpp
index 3b831ba..22d3e70 100644
--- a/src/SFML/Graphics/Transform.cpp
+++ b/src/SFML/Graphics/Transform.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -269,4 +269,23 @@ Vector2f operator *(const Transform& left, const Vector2f& right)
return left.transformPoint(right);
}
+
+////////////////////////////////////////////////////////////
+bool operator ==(const Transform& left, const Transform& right)
+{
+ const float* a = left.getMatrix();
+ const float* b = right.getMatrix();
+
+ return ((a[0] == b[0]) && (a[1] == b[1]) && (a[3] == b[3]) &&
+ (a[4] == b[4]) && (a[5] == b[5]) && (a[7] == b[7]) &&
+ (a[12] == b[12]) && (a[13] == b[13]) && (a[15] == b[15]));
+}
+
+
+////////////////////////////////////////////////////////////
+bool operator !=(const Transform& left, const Transform& right)
+{
+ return !(left == right);
+}
+
} // namespace sf
diff --git a/src/SFML/Graphics/Transformable.cpp b/src/SFML/Graphics/Transformable.cpp
index 851ab3e..8101670 100644
--- a/src/SFML/Graphics/Transformable.cpp
+++ b/src/SFML/Graphics/Transformable.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/Vertex.cpp b/src/SFML/Graphics/Vertex.cpp
index 3d344c1..2655f73 100644
--- a/src/SFML/Graphics/Vertex.cpp
+++ b/src/SFML/Graphics/Vertex.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/VertexArray.cpp b/src/SFML/Graphics/VertexArray.cpp
index 0f9c813..58c98f7 100644
--- a/src/SFML/Graphics/VertexArray.cpp
+++ b/src/SFML/Graphics/VertexArray.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Graphics/VertexBuffer.cpp b/src/SFML/Graphics/VertexBuffer.cpp
new file mode 100644
index 0000000..8e07980
--- /dev/null
+++ b/src/SFML/Graphics/VertexBuffer.cpp
@@ -0,0 +1,363 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Graphics/VertexBuffer.hpp>
+#include <SFML/Graphics/RenderTarget.hpp>
+#include <SFML/Graphics/Vertex.hpp>
+#include <SFML/Graphics/GLCheck.hpp>
+#include <SFML/System/Mutex.hpp>
+#include <SFML/System/Lock.hpp>
+#include <SFML/System/Err.hpp>
+#include <cstring>
+
+namespace
+{
+ sf::Mutex isAvailableMutex;
+
+ GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
+ {
+ switch (usage)
+ {
+ case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW;
+ case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW;
+ default: return GLEXT_GL_STREAM_DRAW;
+ }
+ }
+}
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+VertexBuffer::VertexBuffer() :
+m_buffer (0),
+m_size (0),
+m_primitiveType(Points),
+m_usage (Stream)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::VertexBuffer(PrimitiveType type) :
+m_buffer (0),
+m_size (0),
+m_primitiveType(type),
+m_usage (Stream)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::VertexBuffer(VertexBuffer::Usage usage) :
+m_buffer (0),
+m_size (0),
+m_primitiveType(Points),
+m_usage (usage)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::VertexBuffer(PrimitiveType type, VertexBuffer::Usage usage) :
+m_buffer (0),
+m_size (0),
+m_primitiveType(type),
+m_usage (usage)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::VertexBuffer(const VertexBuffer& copy) :
+m_buffer (0),
+m_size (0),
+m_primitiveType(copy.m_primitiveType),
+m_usage (copy.m_usage)
+{
+ if (copy.m_buffer && copy.m_size)
+ {
+ if (!create(copy.m_size))
+ {
+ err() << "Could not create vertex buffer for copying" << std::endl;
+ return;
+ }
+
+ if (!update(copy))
+ err() << "Could not copy vertex buffer" << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::~VertexBuffer()
+{
+ if (m_buffer)
+ {
+ TransientContextLock contextLock;
+
+ glCheck(GLEXT_glDeleteBuffers(1, &m_buffer));
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool VertexBuffer::create(std::size_t vertexCount)
+{
+ if (!isAvailable())
+ return false;
+
+ TransientContextLock contextLock;
+
+ if (!m_buffer)
+ glCheck(GLEXT_glGenBuffers(1, &m_buffer));
+
+ if (!m_buffer)
+ {
+ err() << "Could not create vertex buffer, generation failed" << std::endl;
+ return false;
+ }
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
+ glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
+
+ m_size = vertexCount;
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t VertexBuffer::getVertexCount() const
+{
+ return m_size;
+}
+
+
+////////////////////////////////////////////////////////////
+bool VertexBuffer::update(const Vertex* vertices)
+{
+ return update(vertices, m_size, 0);
+}
+
+
+////////////////////////////////////////////////////////////
+bool VertexBuffer::update(const Vertex* vertices, std::size_t vertexCount, unsigned int offset)
+{
+ // Sanity checks
+ if (!m_buffer)
+ return false;
+
+ if (!vertices)
+ return false;
+
+ if (offset && (offset + vertexCount > m_size))
+ return false;
+
+ TransientContextLock contextLock;
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
+
+ // Check if we need to resize or orphan the buffer
+ if (vertexCount >= m_size)
+ {
+ glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
+
+ m_size = vertexCount;
+ }
+
+ glCheck(GLEXT_glBufferSubData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * offset, sizeof(Vertex) * vertexCount, vertices));
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool VertexBuffer::update(const VertexBuffer& vertexBuffer)
+{
+#ifdef SFML_OPENGL_ES
+
+ return false;
+
+#else
+
+ if (!m_buffer || !vertexBuffer.m_buffer)
+ return false;
+
+ TransientContextLock contextLock;
+
+ // Make sure that extensions are initialized
+ sf::priv::ensureExtensionsInit();
+
+ if (GLEXT_copy_buffer)
+ {
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_READ_BUFFER, vertexBuffer.m_buffer));
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_WRITE_BUFFER, m_buffer));
+
+ glCheck(GLEXT_glCopyBufferSubData(GLEXT_GL_COPY_READ_BUFFER, GLEXT_GL_COPY_WRITE_BUFFER, 0, 0, sizeof(Vertex) * vertexBuffer.m_size));
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_WRITE_BUFFER, 0));
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_COPY_READ_BUFFER, 0));
+
+ return true;
+ }
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
+ glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, usageToGlEnum(m_usage)));
+
+ void* destination = 0;
+ glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, vertexBuffer.m_buffer));
+
+ void* source = 0;
+ glCheck(source = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_READ_ONLY));
+
+ std::memcpy(destination, source, sizeof(Vertex) * vertexBuffer.m_size);
+
+ GLboolean sourceResult = GL_FALSE;
+ glCheck(sourceResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
+
+ GLboolean destinationResult = GL_FALSE;
+ glCheck(destinationResult = GLEXT_glUnmapBuffer(GLEXT_GL_ARRAY_BUFFER));
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
+
+ if ((sourceResult == GL_FALSE) || (destinationResult == GL_FALSE))
+ return false;
+
+ return true;
+
+#endif // SFML_OPENGL_ES
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer& VertexBuffer::operator =(const VertexBuffer& right)
+{
+ VertexBuffer temp(right);
+
+ swap(temp);
+
+ return *this;
+}
+
+
+////////////////////////////////////////////////////////////
+void VertexBuffer::swap(VertexBuffer& right)
+{
+ std::swap(m_size, right.m_size);
+ std::swap(m_buffer, right.m_buffer);
+ std::swap(m_primitiveType, right.m_primitiveType);
+ std::swap(m_usage, right.m_usage);
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int VertexBuffer::getNativeHandle() const
+{
+ return m_buffer;
+}
+
+
+////////////////////////////////////////////////////////////
+void VertexBuffer::bind(const VertexBuffer* vertexBuffer)
+{
+ if (!isAvailable())
+ return;
+
+ TransientContextLock lock;
+
+ glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, vertexBuffer ? vertexBuffer->m_buffer : 0));
+}
+
+
+////////////////////////////////////////////////////////////
+void VertexBuffer::setPrimitiveType(PrimitiveType type)
+{
+ m_primitiveType = type;
+}
+
+
+////////////////////////////////////////////////////////////
+PrimitiveType VertexBuffer::getPrimitiveType() const
+{
+ return m_primitiveType;
+}
+
+
+////////////////////////////////////////////////////////////
+void VertexBuffer::setUsage(VertexBuffer::Usage usage)
+{
+ m_usage = usage;
+}
+
+
+////////////////////////////////////////////////////////////
+VertexBuffer::Usage VertexBuffer::getUsage() const
+{
+ return m_usage;
+}
+
+
+////////////////////////////////////////////////////////////
+bool VertexBuffer::isAvailable()
+{
+ Lock lock(isAvailableMutex);
+
+ static bool checked = false;
+ static bool available = false;
+
+ if (!checked)
+ {
+ checked = true;
+
+ TransientContextLock contextLock;
+
+ // Make sure that extensions are initialized
+ sf::priv::ensureExtensionsInit();
+
+ available = GLEXT_vertex_buffer_object;
+ }
+
+ return available;
+}
+
+
+////////////////////////////////////////////////////////////
+void VertexBuffer::draw(RenderTarget& target, RenderStates states) const
+{
+ if (m_buffer && m_size)
+ target.draw(*this, 0, m_size, states);
+}
+
+} // namespace sf
diff --git a/src/SFML/Graphics/View.cpp b/src/SFML/Graphics/View.cpp
index 09a45bd..0fcf654 100644
--- a/src/SFML/Graphics/View.cpp
+++ b/src/SFML/Graphics/View.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Main/CMakeLists.txt b/src/SFML/Main/CMakeLists.txt
index d18ee40..6542e59 100644
--- a/src/SFML/Main/CMakeLists.txt
+++ b/src/SFML/Main/CMakeLists.txt
@@ -12,26 +12,20 @@ elseif(SFML_OS_ANDROID)
else()
return()
endif()
-source_group("" FILES ${SRC})
# define the sfml-main target
-add_library(sfml-main STATIC ${SRC})
+sfml_add_library(sfml-main STATIC SOURCES ${SRC})
-# set the debug suffix
-set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
-
-# insert the major version number in the output filename
-set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
-
-# set the target's folder (for IDEs that support it, e.g. Visual Studio)
-set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
-
-# setup the install rule
-install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
+# overwrite sfml-main suffix for backward compatibility with FindSFML.cmake
+set_target_properties(sfml-main PROPERTIES
+ DEBUG_POSTFIX -d
+ RELEASE_POSTFIX ""
+ MINSIZEREL_POSTFIX ""
+ RELWITHDEBINFO_POSTFIX "")
# because of a current limitation on Android (which prevents one library
# from depending on shared libraries), we need a boostrap activity which
# will load our shared libraries manually
if(SFML_OS_ANDROID)
- sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp)
+ sfml_add_library(sfml-activity SOURCES ${SRCROOT}/SFMLActivity.cpp)
endif()
diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp
index 595a3a2..fcb8500 100644
--- a/src/SFML/Main/MainAndroid.cpp
+++ b/src/SFML/Main/MainAndroid.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -45,6 +45,7 @@
#include <SFML/System/Err.hpp>
#include <android/window.h>
#include <android/native_activity.h>
+#include <cstring>
extern int main(int argc, char *argv[]);
@@ -485,7 +486,7 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
{
states->savedState = malloc(savedStateSize);
states->savedStateSize = savedStateSize;
- memcpy(states->savedState, savedState, savedStateSize);
+ std::memcpy(states->savedState, savedState, savedStateSize);
}
states->mainOver = false;
diff --git a/src/SFML/Main/MainWin32.cpp b/src/SFML/Main/MainWin32.cpp
index 4658d9f..fefc1b7 100644
--- a/src/SFML/Main/MainWin32.cpp
+++ b/src/SFML/Main/MainWin32.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -41,14 +41,6 @@
#include <windows.h>
-// Inform the Nvidia/AMD driver that this SFML application could
-// benefit from using the more powerful discrete GPU
-extern "C"
-{
-__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
-__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
-}
-
extern int main(int argc, char* argv[]);
////////////////////////////////////////////////////////////
diff --git a/src/SFML/Main/MainiOS.mm b/src/SFML/Main/MainiOS.mm
index c6bddcc..fa88e69 100644
--- a/src/SFML/Main/MainiOS.mm
+++ b/src/SFML/Main/MainiOS.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.prg)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.prg)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Main/SFMLActivity.cpp b/src/SFML/Main/SFMLActivity.cpp
index 07602fb..caf191b 100644
--- a/src/SFML/Main/SFMLActivity.cpp
+++ b/src/SFML/Main/SFMLActivity.cpp
@@ -28,7 +28,9 @@
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <jni.h>
+#include <string>
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml-activity", __VA_ARGS__))
diff --git a/src/SFML/Network/CMakeLists.txt b/src/SFML/Network/CMakeLists.txt
index d1ff757..6626d73 100644
--- a/src/SFML/Network/CMakeLists.txt
+++ b/src/SFML/Network/CMakeLists.txt
@@ -44,14 +44,12 @@ endif()
source_group("" FILES ${SRC})
-# build the list of external libraries to link
-set(NETWORK_EXT_LIBS)
-if(SFML_OS_WINDOWS)
- set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32)
-endif()
-
# define the sfml-network target
sfml_add_library(sfml-network
- SOURCES ${SRC}
- DEPENDS sfml-system
- EXTERNAL_LIBS ${NETWORK_EXT_LIBS})
+ SOURCES ${SRC})
+
+# setup dependencies
+target_link_libraries(sfml-network PUBLIC sfml-system)
+if(SFML_OS_WINDOWS)
+ target_link_libraries(sfml-network PRIVATE ws2_32)
+endif()
diff --git a/src/SFML/Network/Ftp.cpp b/src/SFML/Network/Ftp.cpp
index 1882da8..41a630f 100644
--- a/src/SFML/Network/Ftp.cpp
+++ b/src/SFML/Network/Ftp.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -322,7 +322,7 @@ Ftp::Response Ftp::download(const std::string& remoteFile, const std::string& lo
////////////////////////////////////////////////////////////
-Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remotePath, TransferMode mode)
+Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remotePath, TransferMode mode, bool append)
{
// Get the contents of the file to send
std::ifstream file(localFile.c_str(), std::ios_base::binary);
@@ -346,7 +346,7 @@ Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remot
if (response.isOk())
{
// Tell the server to start the transfer
- response = sendCommand("STOR", path + filename);
+ response = sendCommand(append ? "APPE" : "STOR", path + filename);
if (response.isOk())
{
// Send the file data
@@ -463,7 +463,7 @@ Ftp::Response Ftp::getResponse()
}
// Save the remaining data for the next time getResponse() is called
- m_receiveBuffer.assign(buffer + in.tellg(), length - in.tellg());
+ m_receiveBuffer.assign(buffer + static_cast<std::size_t>(in.tellg()), length - static_cast<std::size_t>(in.tellg()));
// Return the response code and message
return Response(static_cast<Response::Status>(code), message);
@@ -631,7 +631,7 @@ void Ftp::DataChannel::send(std::istream& stream)
break;
}
- count = stream.gcount();
+ count = static_cast<std::size_t>(stream.gcount());
if (count > 0)
{
diff --git a/src/SFML/Network/Http.cpp b/src/SFML/Network/Http.cpp
index ef6987f..7fdc81a 100644
--- a/src/SFML/Network/Http.cpp
+++ b/src/SFML/Network/Http.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/IpAddress.cpp b/src/SFML/Network/IpAddress.cpp
index 91eec78..9556138 100644
--- a/src/SFML/Network/IpAddress.cpp
+++ b/src/SFML/Network/IpAddress.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/Packet.cpp b/src/SFML/Network/Packet.cpp
index fc33355..0dc2bbc 100644
--- a/src/SFML/Network/Packet.cpp
+++ b/src/SFML/Network/Packet.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/Socket.cpp b/src/SFML/Network/Socket.cpp
index ad6d993..d100421 100644
--- a/src/SFML/Network/Socket.cpp
+++ b/src/SFML/Network/Socket.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/SocketImpl.hpp b/src/SFML/Network/SocketImpl.hpp
index 6f0c7e1..d1ffebe 100644
--- a/src/SFML/Network/SocketImpl.hpp
+++ b/src/SFML/Network/SocketImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/SocketSelector.cpp b/src/SFML/Network/SocketSelector.cpp
index d7c9c56..fa00c63 100644
--- a/src/SFML/Network/SocketSelector.cpp
+++ b/src/SFML/Network/SocketSelector.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/TcpListener.cpp b/src/SFML/Network/TcpListener.cpp
index 713301e..399f87d 100644
--- a/src/SFML/Network/TcpListener.cpp
+++ b/src/SFML/Network/TcpListener.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -63,6 +63,9 @@ unsigned short TcpListener::getLocalPort() const
////////////////////////////////////////////////////////////
Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address)
{
+ // Close the socket if it is already bound
+ close();
+
// Create the internal socket if it doesn't exist
create();
@@ -80,7 +83,7 @@ Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address
}
// Listen to the bound port
- if (::listen(getHandle(), 0) == -1)
+ if (::listen(getHandle(), SOMAXCONN) == -1)
{
// Oops, socket is deaf
err() << "Failed to listen to port " << port << std::endl;
diff --git a/src/SFML/Network/TcpSocket.cpp b/src/SFML/Network/TcpSocket.cpp
index be218cf..e11f76b 100644
--- a/src/SFML/Network/TcpSocket.cpp
+++ b/src/SFML/Network/TcpSocket.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -118,6 +118,9 @@ unsigned short TcpSocket::getRemotePort() const
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
{
+ // Disconnect the socket if it is already connected
+ disconnect();
+
// Create the internal socket if it doesn't exist
create();
diff --git a/src/SFML/Network/UdpSocket.cpp b/src/SFML/Network/UdpSocket.cpp
index 81e2e49..0ff03b0 100644
--- a/src/SFML/Network/UdpSocket.cpp
+++ b/src/SFML/Network/UdpSocket.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -66,6 +66,9 @@ unsigned short UdpSocket::getLocalPort() const
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::bind(unsigned short port, const IpAddress& address)
{
+ // Close the socket if it is already bound
+ close();
+
// Create the internal socket if it doesn't exist
create();
diff --git a/src/SFML/Network/Unix/SocketImpl.cpp b/src/SFML/Network/Unix/SocketImpl.cpp
index 0c1457f..4029480 100644
--- a/src/SFML/Network/Unix/SocketImpl.cpp
+++ b/src/SFML/Network/Unix/SocketImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/Unix/SocketImpl.hpp b/src/SFML/Network/Unix/SocketImpl.hpp
index df99d3b..b70c077 100644
--- a/src/SFML/Network/Unix/SocketImpl.hpp
+++ b/src/SFML/Network/Unix/SocketImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/Win32/SocketImpl.cpp b/src/SFML/Network/Win32/SocketImpl.cpp
index 0e9f6ae..bd53665 100644
--- a/src/SFML/Network/Win32/SocketImpl.cpp
+++ b/src/SFML/Network/Win32/SocketImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Network/Win32/SocketImpl.hpp b/src/SFML/Network/Win32/SocketImpl.hpp
index 254fad2..978336f 100644
--- a/src/SFML/Network/Win32/SocketImpl.hpp
+++ b/src/SFML/Network/Win32/SocketImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Android/Activity.cpp b/src/SFML/System/Android/Activity.cpp
index 4f657ee..5d14026 100644
--- a/src/SFML/System/Android/Activity.cpp
+++ b/src/SFML/System/Android/Activity.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -43,7 +43,7 @@ std::streambuf::int_type LogcatStream::overflow (std::streambuf::int_type c)
if (c == "\n"[0])
{
m_message.push_back(c);
- LOGE(m_message.c_str());
+ LOGE("%s", m_message.c_str());
m_message.clear();
}
diff --git a/src/SFML/System/Android/NativeActivity.cpp b/src/SFML/System/Android/NativeActivity.cpp
index ff97501..ac489ae 100644
--- a/src/SFML/System/Android/NativeActivity.cpp
+++ b/src/SFML/System/Android/NativeActivity.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt
index 54da9a0..d1b712d 100644
--- a/src/SFML/System/CMakeLists.txt
+++ b/src/SFML/System/CMakeLists.txt
@@ -85,21 +85,18 @@ else()
source_group("unix" FILES ${PLATFORM_SRC})
endif()
-# build the list of external libraries to link
+# define the sfml-system target
+sfml_add_library(sfml-system
+ SOURCES ${SRC} ${PLATFORM_SRC})
+
+# setup dependencies
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
- list(APPEND SYSTEM_EXT_LIBS pthread)
+ target_link_libraries(sfml-system PRIVATE pthread)
endif()
if(SFML_OS_LINUX)
- list(APPEND SYSTEM_EXT_LIBS rt)
-endif()
-if(SFML_OS_WINDOWS)
- list(APPEND SYSTEM_EXT_LIBS winmm)
+ target_link_libraries(sfml-system PRIVATE rt)
+elseif(SFML_OS_WINDOWS)
+ target_link_libraries(sfml-system PRIVATE winmm)
+elseif(SFML_OS_ANDROID)
+ target_link_libraries(sfml-system PRIVATE android log)
endif()
-if(SFML_OS_ANDROID)
- list(APPEND SYSTEM_EXT_LIBS android log)
-endif()
-
-# define the sfml-system target
-sfml_add_library(sfml-system
- SOURCES ${SRC} ${PLATFORM_SRC}
- EXTERNAL_LIBS ${SYSTEM_EXT_LIBS})
diff --git a/src/SFML/System/Clock.cpp b/src/SFML/System/Clock.cpp
index e4f347e..9f09533 100644
--- a/src/SFML/System/Clock.cpp
+++ b/src/SFML/System/Clock.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Err.cpp b/src/SFML/System/Err.cpp
index 5d2084e..d186931 100644
--- a/src/SFML/System/Err.cpp
+++ b/src/SFML/System/Err.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/FileInputStream.cpp b/src/SFML/System/FileInputStream.cpp
index e6f1c83..852470d 100644
--- a/src/SFML/System/FileInputStream.cpp
+++ b/src/SFML/System/FileInputStream.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -95,7 +95,7 @@ Int64 FileInputStream::seek(Int64 position)
#else
if (m_file)
{
- if (std::fseek(m_file, static_cast<std::size_t>(position), SEEK_SET))
+ if (std::fseek(m_file, static_cast<long>(position), SEEK_SET))
return -1;
return tell();
diff --git a/src/SFML/System/Lock.cpp b/src/SFML/System/Lock.cpp
index 4a37127..ada1ca1 100644
--- a/src/SFML/System/Lock.cpp
+++ b/src/SFML/System/Lock.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/MemoryInputStream.cpp b/src/SFML/System/MemoryInputStream.cpp
index e312927..3bd02b4 100644
--- a/src/SFML/System/MemoryInputStream.cpp
+++ b/src/SFML/System/MemoryInputStream.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Mutex.cpp b/src/SFML/System/Mutex.cpp
index 36d48ee..139bf56 100644
--- a/src/SFML/System/Mutex.cpp
+++ b/src/SFML/System/Mutex.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Sleep.cpp b/src/SFML/System/Sleep.cpp
index 4f2a50e..35db5e8 100644
--- a/src/SFML/System/Sleep.cpp
+++ b/src/SFML/System/Sleep.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/String.cpp b/src/SFML/System/String.cpp
index 94b8b82..d8831f9 100644
--- a/src/SFML/System/String.cpp
+++ b/src/SFML/System/String.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Thread.cpp b/src/SFML/System/Thread.cpp
index 3a2c0f9..098018a 100644
--- a/src/SFML/System/Thread.cpp
+++ b/src/SFML/System/Thread.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/ThreadLocal.cpp b/src/SFML/System/ThreadLocal.cpp
index 01e3a35..62d8117 100644
--- a/src/SFML/System/ThreadLocal.cpp
+++ b/src/SFML/System/ThreadLocal.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Time.cpp b/src/SFML/System/Time.cpp
index 63de359..681c9a9 100644
--- a/src/SFML/System/Time.cpp
+++ b/src/SFML/System/Time.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/ClockImpl.cpp b/src/SFML/System/Unix/ClockImpl.cpp
index 2cd89cf..0d4f2bd 100644
--- a/src/SFML/System/Unix/ClockImpl.cpp
+++ b/src/SFML/System/Unix/ClockImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/ClockImpl.hpp b/src/SFML/System/Unix/ClockImpl.hpp
index 26c6433..56f550c 100644
--- a/src/SFML/System/Unix/ClockImpl.hpp
+++ b/src/SFML/System/Unix/ClockImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/MutexImpl.cpp b/src/SFML/System/Unix/MutexImpl.cpp
index 2ab46c0..cc4e38e 100644
--- a/src/SFML/System/Unix/MutexImpl.cpp
+++ b/src/SFML/System/Unix/MutexImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/MutexImpl.hpp b/src/SFML/System/Unix/MutexImpl.hpp
index ea4c838..cf0c0dd 100644
--- a/src/SFML/System/Unix/MutexImpl.hpp
+++ b/src/SFML/System/Unix/MutexImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/SleepImpl.cpp b/src/SFML/System/Unix/SleepImpl.cpp
index 22b6f35..f6fb608 100644
--- a/src/SFML/System/Unix/SleepImpl.cpp
+++ b/src/SFML/System/Unix/SleepImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/SleepImpl.hpp b/src/SFML/System/Unix/SleepImpl.hpp
index a4039b6..8d146d4 100644
--- a/src/SFML/System/Unix/SleepImpl.hpp
+++ b/src/SFML/System/Unix/SleepImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/ThreadImpl.cpp b/src/SFML/System/Unix/ThreadImpl.cpp
index b6dd383..e80213f 100644
--- a/src/SFML/System/Unix/ThreadImpl.cpp
+++ b/src/SFML/System/Unix/ThreadImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -65,7 +65,7 @@ void ThreadImpl::terminate()
#ifndef SFML_SYSTEM_ANDROID
pthread_cancel(m_thread);
#else
- // See http://stackoverflow.com/questions/4610086/pthread-cancel-al
+ // See https://stackoverflow.com/questions/4610086/pthread-cancel-al
pthread_kill(m_thread, SIGUSR1);
#endif
}
diff --git a/src/SFML/System/Unix/ThreadImpl.hpp b/src/SFML/System/Unix/ThreadImpl.hpp
index 0191d5e..2cd13d0 100644
--- a/src/SFML/System/Unix/ThreadImpl.hpp
+++ b/src/SFML/System/Unix/ThreadImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/ThreadLocalImpl.cpp b/src/SFML/System/Unix/ThreadLocalImpl.cpp
index a0a157e..1fea0c9 100644
--- a/src/SFML/System/Unix/ThreadLocalImpl.cpp
+++ b/src/SFML/System/Unix/ThreadLocalImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Unix/ThreadLocalImpl.hpp b/src/SFML/System/Unix/ThreadLocalImpl.hpp
index b72ce65..919dcd5 100644
--- a/src/SFML/System/Unix/ThreadLocalImpl.hpp
+++ b/src/SFML/System/Unix/ThreadLocalImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/ClockImpl.cpp b/src/SFML/System/Win32/ClockImpl.cpp
index 8098a7d..f69da4b 100644
--- a/src/SFML/System/Win32/ClockImpl.cpp
+++ b/src/SFML/System/Win32/ClockImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -33,8 +33,6 @@
namespace
{
- sf::Mutex oldWindowsMutex;
-
LARGE_INTEGER getFrequency()
{
LARGE_INTEGER frequency;
@@ -67,6 +65,8 @@ Time ClockImpl::getCurrentTime()
if (oldWindows)
{
+ static sf::Mutex oldWindowsMutex;
+
// Acquire a lock (CRITICAL_SECTION) to prevent travelling back in time
Lock lock(oldWindowsMutex);
diff --git a/src/SFML/System/Win32/ClockImpl.hpp b/src/SFML/System/Win32/ClockImpl.hpp
index 45e08e8..d40ec6f 100644
--- a/src/SFML/System/Win32/ClockImpl.hpp
+++ b/src/SFML/System/Win32/ClockImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/MutexImpl.cpp b/src/SFML/System/Win32/MutexImpl.cpp
index 7b47cd5..8fdd388 100644
--- a/src/SFML/System/Win32/MutexImpl.cpp
+++ b/src/SFML/System/Win32/MutexImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/MutexImpl.hpp b/src/SFML/System/Win32/MutexImpl.hpp
index c7174e8..9572114 100644
--- a/src/SFML/System/Win32/MutexImpl.hpp
+++ b/src/SFML/System/Win32/MutexImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/SleepImpl.cpp b/src/SFML/System/Win32/SleepImpl.cpp
index 8a8eee1..41c1018 100644
--- a/src/SFML/System/Win32/SleepImpl.cpp
+++ b/src/SFML/System/Win32/SleepImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/SleepImpl.hpp b/src/SFML/System/Win32/SleepImpl.hpp
index 2cde5b3..ad0138d 100644
--- a/src/SFML/System/Win32/SleepImpl.hpp
+++ b/src/SFML/System/Win32/SleepImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/ThreadImpl.cpp b/src/SFML/System/Win32/ThreadImpl.cpp
index d34950a..f5d2e2e 100644
--- a/src/SFML/System/Win32/ThreadImpl.cpp
+++ b/src/SFML/System/Win32/ThreadImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/ThreadImpl.hpp b/src/SFML/System/Win32/ThreadImpl.hpp
index cfd1039..913585f 100644
--- a/src/SFML/System/Win32/ThreadImpl.hpp
+++ b/src/SFML/System/Win32/ThreadImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/ThreadLocalImpl.cpp b/src/SFML/System/Win32/ThreadLocalImpl.cpp
index 221fffe..bd28da3 100644
--- a/src/SFML/System/Win32/ThreadLocalImpl.cpp
+++ b/src/SFML/System/Win32/ThreadLocalImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/System/Win32/ThreadLocalImpl.hpp b/src/SFML/System/Win32/ThreadLocalImpl.hpp
index 458b28a..e617dfe 100644
--- a/src/SFML/System/Win32/ThreadLocalImpl.hpp
+++ b/src/SFML/System/Win32/ThreadLocalImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Android/ClipboardImpl.cpp b/src/SFML/Window/Android/ClipboardImpl.cpp
new file mode 100644
index 0000000..a5d3a19
--- /dev/null
+++ b/src/SFML/Window/Android/ClipboardImpl.cpp
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Android/ClipboardImpl.hpp>
+#include <SFML/System/Err.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getString()
+{
+ sf::err() << "Clipboard API not implemented for Android.\n";
+ return String();
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ sf::err() << "Clipboard API not implemented for Android.\n";
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Android/ClipboardImpl.hpp b/src/SFML/Window/Android/ClipboardImpl.hpp
new file mode 100644
index 0000000..8d33dc6
--- /dev/null
+++ b/src/SFML/Window/Android/ClipboardImpl.hpp
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPLANDROID_HPP
+#define SFML_CLIPBOARDIMPLANDROID_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class ClipboardImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String object containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARDIMPLANDROID_HPP
diff --git a/src/SFML/Window/Android/CursorImpl.cpp b/src/SFML/Window/Android/CursorImpl.cpp
new file mode 100644
index 0000000..da5fff5
--- /dev/null
+++ b/src/SFML/Window/Android/CursorImpl.cpp
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Android/CursorImpl.hpp>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+CursorImpl::CursorImpl()
+{
+ // Nothing.
+}
+
+
+////////////////////////////////////////////////////////////
+CursorImpl::~CursorImpl()
+{
+ // Nothing.
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ // Not supported
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromSystem(Cursor::Type type)
+{
+ // Not supported
+ return false;
+}
+
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/Android/CursorImpl.hpp b/src/SFML/Window/Android/CursorImpl.hpp
new file mode 100644
index 0000000..fe5f948
--- /dev/null
+++ b/src/SFML/Window/Android/CursorImpl.hpp
@@ -0,0 +1,88 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPLANDROID_HPP
+#define SFML_CURSORIMPLANDROID_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+
+
+namespace sf
+{
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Android implementation of Cursor
+///
+/// This is a typical "not supported" implementation.
+///
+////////////////////////////////////////////////////////////
+class CursorImpl : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Refer to sf::Cursor::Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// Refer to sf::Cursor::~Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ ~CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// Returns false.
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Returns false.
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Cursor::Type type);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_CURSORIMPLANDROID_HPP
diff --git a/src/SFML/Window/Android/SensorImpl.cpp b/src/SFML/Window/Android/SensorImpl.cpp
index 201c3eb..3a018b5 100644
--- a/src/SFML/Window/Android/SensorImpl.cpp
+++ b/src/SFML/Window/Android/SensorImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Android/SensorImpl.hpp b/src/SFML/Window/Android/SensorImpl.hpp
index 5cae66b..4ce19a4 100644
--- a/src/SFML/Window/Android/SensorImpl.hpp
+++ b/src/SFML/Window/Android/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp
index 27d2f10..40992a0 100644
--- a/src/SFML/Window/Android/WindowImplAndroid.cpp
+++ b/src/SFML/Window/Android/WindowImplAndroid.cpp
@@ -186,6 +186,13 @@ void WindowImplAndroid::setMouseCursorGrabbed(bool grabbed)
////////////////////////////////////////////////////////////
+void WindowImplAndroid::setMouseCursor(const CursorImpl& cursor)
+{
+ // Not applicable
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplAndroid::setKeyRepeatEnabled(bool enabled)
{
// Not applicable
@@ -411,7 +418,7 @@ int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* stat
if (key == AKEYCODE_UNKNOWN)
{
// This is a unique sequence, which is not yet exposed in the NDK
- // http://code.google.com/p/android/issues/detail?id=33998
+ // https://code.google.com/p/android/issues/detail?id=33998
return 0;
}
else if (int unicode = getUnicode(_event)) // This is a repeated sequence
@@ -612,15 +619,16 @@ Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key)
case AKEYCODE_SYM:
case AKEYCODE_EXPLORER:
case AKEYCODE_ENVELOPE: return Keyboard::Unknown;
- case AKEYCODE_ENTER: return Keyboard::Return;
- case AKEYCODE_DEL: return Keyboard::Delete;
+ case AKEYCODE_ENTER: return Keyboard::Enter;
+ case AKEYCODE_DEL: return Keyboard::Backspace;
+ case AKEYCODE_FORWARD_DEL: return Keyboard::Delete;
case AKEYCODE_GRAVE: return Keyboard::Tilde;
case AKEYCODE_MINUS: return Keyboard::Subtract;
case AKEYCODE_EQUALS: return Keyboard::Equal;
case AKEYCODE_LEFT_BRACKET: return Keyboard::LBracket;
case AKEYCODE_RIGHT_BRACKET: return Keyboard::RBracket;
- case AKEYCODE_BACKSLASH: return Keyboard::BackSlash;
- case AKEYCODE_SEMICOLON: return Keyboard::SemiColon;
+ case AKEYCODE_BACKSLASH: return Keyboard::Backslash;
+ case AKEYCODE_SEMICOLON: return Keyboard::Semicolon;
case AKEYCODE_APOSTROPHE: return Keyboard::Quote;
case AKEYCODE_SLASH: return Keyboard::Slash;
case AKEYCODE_AT:
diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp
index 88250d4..7636144 100644
--- a/src/SFML/Window/Android/WindowImplAndroid.hpp
+++ b/src/SFML/Window/Android/WindowImplAndroid.hpp
@@ -155,6 +155,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt
index a887766..916c1dc 100644
--- a/src/SFML/Window/CMakeLists.txt
+++ b/src/SFML/Window/CMakeLists.txt
@@ -4,8 +4,14 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window)
# all source files
set(SRC
+ ${INCROOT}/Clipboard.hpp
+ ${SRCROOT}/Clipboard.cpp
+ ${SRCROOT}/ClipboardImpl.hpp
${SRCROOT}/Context.cpp
${INCROOT}/Context.hpp
+ ${SRCROOT}/Cursor.cpp
+ ${INCROOT}/Cursor.hpp
+ ${SRCROOT}/CursorImpl.hpp
${INCROOT}/Export.hpp
${SRCROOT}/GlContext.cpp
${SRCROOT}/GlContext.hpp
@@ -51,6 +57,10 @@ source_group("" FILES ${SRC})
# add platform specific sources
if(SFML_OS_WINDOWS)
set(PLATFORM_SRC
+ ${SRCROOT}/Win32/CursorImpl.hpp
+ ${SRCROOT}/Win32/CursorImpl.cpp
+ ${SRCROOT}/Win32/ClipboardImpl.hpp
+ ${SRCROOT}/Win32/ClipboardImpl.cpp
${SRCROOT}/Win32/WglContext.cpp
${SRCROOT}/Win32/WglContext.hpp
${SRCROOT}/Win32/WglExtensions.cpp
@@ -69,8 +79,12 @@ if(SFML_OS_WINDOWS)
# make sure that we use the Unicode version of the Win API functions
add_definitions(-DUNICODE -D_UNICODE)
-elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
+elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
set(PLATFORM_SRC
+ ${SRCROOT}/Unix/CursorImpl.hpp
+ ${SRCROOT}/Unix/CursorImpl.cpp
+ ${SRCROOT}/Unix/ClipboardImpl.hpp
+ ${SRCROOT}/Unix/ClipboardImpl.cpp
${SRCROOT}/Unix/Display.cpp
${SRCROOT}/Unix/Display.hpp
${SRCROOT}/Unix/InputImpl.cpp
@@ -102,6 +116,12 @@ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
${SRCROOT}/FreeBSD/JoystickImpl.cpp
${SRCROOT}/FreeBSD/JoystickImpl.hpp
)
+ elseif(SFML_OS_OPENBSD)
+ set(PLATFORM_SRC
+ ${PLATFORM_SRC}
+ ${SRCROOT}/OpenBSD/JoystickImpl.cpp
+ ${SRCROOT}/OpenBSD/JoystickImpl.hpp
+ )
endif()
source_group("unix" FILES ${PLATFORM_SRC})
elseif(SFML_OS_MACOSX)
@@ -110,6 +130,10 @@ elseif(SFML_OS_MACOSX)
${SRCROOT}/OSX/cpp_objc_conversion.mm
${SRCROOT}/OSX/cg_sf_conversion.hpp
${SRCROOT}/OSX/cg_sf_conversion.mm
+ ${SRCROOT}/OSX/CursorImpl.hpp
+ ${SRCROOT}/OSX/CursorImpl.mm
+ ${SRCROOT}/OSX/ClipboardImpl.hpp
+ ${SRCROOT}/OSX/ClipboardImpl.mm
${SRCROOT}/OSX/InputImpl.mm
${SRCROOT}/OSX/InputImpl.hpp
${SRCROOT}/OSX/HIDInputManager.hpp
@@ -155,6 +179,10 @@ elseif(SFML_OS_MACOSX)
source_group("mac" FILES ${PLATFORM_SRC})
elseif(SFML_OS_IOS)
set(PLATFORM_SRC
+ ${SRCROOT}/iOS/CursorImpl.hpp
+ ${SRCROOT}/iOS/CursorImpl.cpp
+ ${SRCROOT}/iOS/ClipboardImpl.mm
+ ${SRCROOT}/iOS/ClipboardImpl.hpp
${SRCROOT}/iOS/EaglContext.mm
${SRCROOT}/iOS/EaglContext.hpp
${SRCROOT}/iOS/InputImpl.mm
@@ -179,6 +207,10 @@ elseif(SFML_OS_IOS)
source_group("ios" FILES ${PLATFORM_SRC})
elseif(SFML_OS_ANDROID)
set(PLATFORM_SRC
+ ${SRCROOT}/Android/CursorImpl.hpp
+ ${SRCROOT}/Android/CursorImpl.cpp
+ ${SRCROOT}/Android/ClipboardImpl.hpp
+ ${SRCROOT}/Android/ClipboardImpl.cpp
${SRCROOT}/Android/WindowImplAndroid.hpp
${SRCROOT}/Android/WindowImplAndroid.cpp
${SRCROOT}/Android/VideoModeImpl.cpp
@@ -192,63 +224,53 @@ elseif(SFML_OS_ANDROID)
source_group("android" FILES ${PLATFORM_SRC})
endif()
-# find external libraries
-if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
- find_package(X11 REQUIRED)
- if(NOT X11_FOUND)
- message(FATAL_ERROR "X11 library not found")
- endif()
- if(NOT X11_Xrandr_FOUND)
- message(FATAL_ERROR "Xrandr library not found")
- endif()
- include_directories(${X11_INCLUDE_DIR})
-endif()
-if(NOT SFML_OPENGL_ES)
- find_package(OpenGL REQUIRED)
- include_directories(${OPENGL_INCLUDE_DIR})
+# define the sfml-window target
+sfml_add_library(sfml-window
+ SOURCES ${SRC} ${PLATFORM_SRC})
+target_link_libraries(sfml-window PUBLIC sfml-system)
+
+# find and setup usage for external libraries
+if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OPENBSD)
+ sfml_find_package(X11 INCLUDE "X11_INCLUDE_DIR" LINK "X11_X11_LIB" "X11_Xrandr_LIB")
+ target_link_libraries(sfml-window PRIVATE X11)
endif()
-if(SFML_OPENGL_ES AND SFML_OS_LINUX)
- find_package(EGL REQUIRED)
- find_package(GLES REQUIRED)
- include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
+
+if(SFML_OPENGL_ES)
+ if(SFML_OS_IOS)
+ target_link_libraries(sfml-window PRIVATE "-framework OpenGLES")
+ elseif(SFML_OS_ANDROID)
+ target_link_libraries(sfml-window PRIVATE EGL GLESv1_CM)
+ endif()
+else()
+ sfml_find_package(OpenGL INCLUDE "OPENGL_INCLUDE_DIR" LINK "OPENGL_gl_LIBRARY")
+ target_link_libraries(sfml-window PRIVATE OpenGL)
endif()
-if(SFML_OS_LINUX)
- find_package(UDev REQUIRED)
- if(NOT UDEV_FOUND)
- message(FATAL_ERROR "udev library not found")
+
+if(SFML_OS_WINDOWS AND NOT SFML_COMPILER_MSVC)
+ include(CheckIncludeFile)
+ check_include_file(dinput.h DINPUT_H_FOUND)
+ if(NOT DINPUT_H_FOUND)
+ target_include_directories(sfml-window PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/mingw")
endif()
- include_directories(${UDEV_INCLUDE_DIR})
endif()
+if(SFML_OPENGL_ES AND SFML_OS_LINUX)
+ sfml_find_package(EGL INCLUDE "EGL_INCLUDE_DIR" LINK "EGL_LIBRARY")
+ sfml_find_package(GLES INCLUDE "GLES_INCLUDE_DIR" LINK "GLES_LIBRARY")
+ target_link_libraries(sfml-window PRIVATE EGL GLES)
+endif()
-# build the list of external libraries to link
-if(SFML_OS_WINDOWS)
- list(APPEND WINDOW_EXT_LIBS winmm gdi32)
-elseif(SFML_OS_LINUX)
- list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES})
+if(SFML_OS_LINUX)
+ sfml_find_package(UDev INCLUDE "UDEV_INCLUDE_DIR" LINK "UDEV_LIBRARIES")
+ target_link_libraries(sfml-window PRIVATE UDev)
+elseif(SFML_OS_WINDOWS)
+ target_link_libraries(sfml-window PRIVATE winmm gdi32)
elseif(SFML_OS_FREEBSD)
- list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid)
+ target_link_libraries(sfml-window PRIVATE usbhid)
elseif(SFML_OS_MACOSX)
- list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
+ target_link_libraries(sfml-window PRIVATE "-framework Foundation" "-framework AppKit" "-framework IOKit" "-framework Carbon")
elseif(SFML_OS_IOS)
- list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
+ target_link_libraries(sfml-window PRIVATE "-framework Foundation" "-framework UIKit" "-framework CoreGraphics" "-framework QuartzCore" "-framework CoreMotion")
elseif(SFML_OS_ANDROID)
- list(APPEND WINDOW_EXT_LIBS android)
+ target_link_libraries(sfml-window PRIVATE android)
endif()
-if(SFML_OPENGL_ES)
- if(SFML_OS_LINUX)
- list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
- elseif(SFML_OS_IOS)
- list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
- elseif(SFML_OS_ANDROID)
- list(APPEND WINDOW_EXT_LIBS EGL GLESv1_CM)
- endif()
-else()
- list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})
-endif()
-
-# define the sfml-window target
-sfml_add_library(sfml-window
- SOURCES ${SRC} ${PLATFORM_SRC}
- DEPENDS sfml-system
- EXTERNAL_LIBS ${WINDOW_EXT_LIBS})
diff --git a/src/SFML/Window/Clipboard.cpp b/src/SFML/Window/Clipboard.cpp
new file mode 100644
index 0000000..9148c97
--- /dev/null
+++ b/src/SFML/Window/Clipboard.cpp
@@ -0,0 +1,48 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Clipboard.hpp>
+#include <SFML/Window/ClipboardImpl.hpp>
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+String Clipboard::getString()
+{
+ return priv::ClipboardImpl::getString();
+}
+
+
+////////////////////////////////////////////////////////////
+void Clipboard::setString(const String& text)
+{
+ return priv::ClipboardImpl::setString(text);
+}
+
+} // namespace sf
diff --git a/src/SFML/Window/ClipboardImpl.hpp b/src/SFML/Window/ClipboardImpl.hpp
new file mode 100644
index 0000000..8e60d4e
--- /dev/null
+++ b/src/SFML/Window/ClipboardImpl.hpp
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPL_HPP
+#define SFML_CLIPBOARDIMPL_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+
+#if defined(SFML_SYSTEM_WINDOWS)
+ #include <SFML/Window/Win32/ClipboardImpl.hpp>
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
+ #include <SFML/Window/Unix/ClipboardImpl.hpp>
+#elif defined(SFML_SYSTEM_MACOS)
+ #include <SFML/Window/OSX/ClipboardImpl.hpp>
+#elif defined(SFML_SYSTEM_IOS)
+ #include <SFML/Window/iOS/ClipboardImpl.hpp>
+#elif defined(SFML_SYSTEM_ANDROID)
+ #include <SFML/Window/Android/ClipboardImpl.hpp>
+#endif
+
+#endif // SFML_CLIPBOARDIMPL_HPP
diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp
index 321dc2c..4e0a4b8 100644
--- a/src/SFML/Window/Context.cpp
+++ b/src/SFML/Window/Context.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -81,6 +81,13 @@ const Context* Context::getActiveContext()
////////////////////////////////////////////////////////////
+Uint64 Context::getActiveContextId()
+{
+ return priv::GlContext::getActiveContextId();
+}
+
+
+////////////////////////////////////////////////////////////
bool Context::isExtensionAvailable(const char* name)
{
return priv::GlContext::isExtensionAvailable(name);
diff --git a/src/SFML/Window/Cursor.cpp b/src/SFML/Window/Cursor.cpp
new file mode 100644
index 0000000..c71491f
--- /dev/null
+++ b/src/SFML/Window/Cursor.cpp
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/Window/CursorImpl.hpp>
+
+namespace sf
+{
+
+////////////////////////////////////////////////////////////
+Cursor::Cursor() :
+m_impl(new priv::CursorImpl())
+{
+ // That's it
+}
+
+
+////////////////////////////////////////////////////////////
+Cursor::~Cursor()
+{
+ delete m_impl;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Cursor::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ if ((pixels == 0) || (size.x == 0) || (size.y == 0))
+ return false;
+ else
+ return m_impl->loadFromPixels(pixels, size, hotspot);
+}
+
+
+////////////////////////////////////////////////////////////
+bool Cursor::loadFromSystem(Type type)
+{
+ return m_impl->loadFromSystem(type);
+}
+
+
+////////////////////////////////////////////////////////////
+const priv::CursorImpl& Cursor::getImpl() const
+{
+ return *m_impl;
+}
+
+} // namespace sf
+
diff --git a/src/SFML/Window/CursorImpl.hpp b/src/SFML/Window/CursorImpl.hpp
new file mode 100644
index 0000000..d48220c
--- /dev/null
+++ b/src/SFML/Window/CursorImpl.hpp
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPL_HPP
+#define SFML_CURSORIMPL_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+
+#if defined(SFML_SYSTEM_WINDOWS)
+
+ #include <SFML/Window/Win32/CursorImpl.hpp>
+
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
+
+ #include <SFML/Window/Unix/CursorImpl.hpp>
+
+#elif defined(SFML_SYSTEM_MACOS)
+
+ #include <SFML/Window/OSX/CursorImpl.hpp>
+
+#elif defined(SFML_SYSTEM_IOS)
+
+ #include <SFML/Window/iOS/CursorImpl.hpp>
+
+#elif defined(SFML_SYSTEM_ANDROID)
+
+ #include <SFML/Window/Android/CursorImpl.hpp>
+
+#endif
+
+
+#endif // SFML_CURSORIMPL_HPP
diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp
index 03c4197..fb91cda 100644
--- a/src/SFML/Window/EglContext.cpp
+++ b/src/SFML/Window/EglContext.cpp
@@ -150,6 +150,9 @@ m_config (NULL)
////////////////////////////////////////////////////////////
EglContext::~EglContext()
{
+ // Notify unshared OpenGL resources of context destruction
+ cleanupUnsharedResources();
+
// Deactivate the current context
EGLContext currentContext = eglCheck(eglGetCurrentContext());
@@ -243,10 +246,10 @@ EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixe
{
// Set our video settings constraint
const EGLint attributes[] = {
- EGL_BUFFER_SIZE, bitsPerPixel,
- EGL_DEPTH_SIZE, settings.depthBits,
- EGL_STENCIL_SIZE, settings.stencilBits,
- EGL_SAMPLE_BUFFERS, settings.antialiasingLevel,
+ EGL_BUFFER_SIZE, static_cast<EGLint>(bitsPerPixel),
+ EGL_DEPTH_SIZE, static_cast<EGLint>(settings.depthBits),
+ EGL_STENCIL_SIZE, static_cast<EGLint>(settings.stencilBits),
+ EGL_SAMPLE_BUFFERS, static_cast<EGLint>(settings.antialiasingLevel),
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_NONE
diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.cpp b/src/SFML/Window/FreeBSD/JoystickImpl.cpp
index 7636e47..6bc646d 100644
--- a/src/SFML/Window/FreeBSD/JoystickImpl.cpp
+++ b/src/SFML/Window/FreeBSD/JoystickImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
// 2013-2013 David Demelier (demelier.david@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.hpp b/src/SFML/Window/FreeBSD/JoystickImpl.hpp
index 7f57f2f..5b2c029 100644
--- a/src/SFML/Window/FreeBSD/JoystickImpl.hpp
+++ b/src/SFML/Window/FreeBSD/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp
index 396d366..3cbb701 100644
--- a/src/SFML/Window/GlContext.cpp
+++ b/src/SFML/Window/GlContext.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -36,8 +36,10 @@
#include <vector>
#include <string>
#include <set>
+#include <utility>
#include <cstdlib>
#include <cstring>
+#include <cctype>
#include <cassert>
#if !defined(SFML_OPENGL_ES)
@@ -47,7 +49,7 @@
#include <SFML/Window/Win32/WglContext.hpp>
typedef sf::priv::WglContext ContextType;
- #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+ #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
#include <SFML/Window/Unix/GlxContext.hpp>
typedef sf::priv::GlxContext ContextType;
@@ -145,6 +147,16 @@ namespace
// The hidden, inactive context that will be shared with all other contexts
ContextType* sharedContext = NULL;
+ // Unique identifier, used for identifying contexts when managing unshareable OpenGL resources
+ sf::Uint64 id = 1; // start at 1, zero is "no context"
+
+ // Set containing callback functions to be called whenever a
+ // context is going to be destroyed
+ // Unshareable OpenGL resources rely on this to clean up properly
+ // whenever a context containing them is destroyed
+ typedef std::set<std::pair<sf::ContextDestroyCallback, void*> > ContextDestroyCallbacks;
+ ContextDestroyCallbacks contextDestroyCallbacks;
+
// This structure contains all the state necessary to
// track TransientContext usage
struct TransientContext : private sf::NonCopyable
@@ -199,6 +211,26 @@ namespace
// Supported OpenGL extensions
std::vector<std::string> extensions;
+
+ // Helper to parse OpenGL version strings
+ bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
+ {
+ std::size_t prefixLength = std::strlen(prefix);
+
+ if ((std::strlen(version) >= (prefixLength + 3)) &&
+ (std::strncmp(version, prefix, prefixLength) == 0) &&
+ std::isdigit(version[prefixLength]) &&
+ (version[prefixLength + 1] == '.') &&
+ std::isdigit(version[prefixLength + 2]))
+ {
+ major = version[prefixLength] - '0';
+ minor = version[prefixLength + 2] - '0';
+
+ return true;
+ }
+
+ return false;
+ }
}
@@ -305,6 +337,13 @@ void GlContext::cleanupResource()
////////////////////////////////////////////////////////////
+void GlContext::registerContextDestroyCallback(ContextDestroyCallback callback, void* arg)
+{
+ contextDestroyCallbacks.insert(std::make_pair(callback, arg));
+}
+
+
+////////////////////////////////////////////////////////////
void GlContext::acquireTransientContext()
{
// Protect from concurrent access
@@ -453,6 +492,13 @@ GlFunctionPointer GlContext::getFunction(const char* name)
////////////////////////////////////////////////////////////
+Uint64 GlContext::getActiveContextId()
+{
+ return currentContext ? currentContext->m_id : 0;
+}
+
+
+////////////////////////////////////////////////////////////
GlContext::~GlContext()
{
// Deactivate the context before killing it, unless we're inside Cleanup()
@@ -525,7 +571,8 @@ bool GlContext::setActive(bool active)
////////////////////////////////////////////////////////////
-GlContext::GlContext()
+GlContext::GlContext() :
+m_id(id++)
{
// Nothing to do
}
@@ -561,6 +608,29 @@ int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings&
////////////////////////////////////////////////////////////
+void GlContext::cleanupUnsharedResources()
+{
+ // Save the current context so we can restore it later
+ GlContext* contextToRestore = currentContext;
+
+ // If this context is already active there is no need to save it
+ if (contextToRestore == this)
+ contextToRestore = NULL;
+
+ // Make this context active so resources can be freed
+ setActive(true);
+
+ // Call the registered destruction callbacks
+ for (ContextDestroyCallbacks::iterator iter = contextDestroyCallbacks.begin(); iter != contextDestroyCallbacks.end(); ++iter)
+ iter->first(iter->second);
+
+ // Make the originally active context active again
+ if (contextToRestore)
+ contextToRestore->setActive(true);
+}
+
+
+////////////////////////////////////////////////////////////
void GlContext::initialize(const ContextSettings& requestedSettings)
{
// Activate the context
@@ -582,18 +652,30 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
else
{
// Try the old way
- const GLubyte* version = glGetString(GL_VERSION);
+
+ // If we can't get the version number, assume 1.1
+ m_settings.majorVersion = 1;
+ m_settings.minorVersion = 1;
+
+ const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
if (version)
{
- // The beginning of the returned string is "major.minor" (this is standard)
- m_settings.majorVersion = version[0] - '0';
- m_settings.minorVersion = version[2] - '0';
+ // OpenGL ES Common Lite profile: The beginning of the returned string is "OpenGL ES-CL major.minor"
+ // OpenGL ES Common profile: The beginning of the returned string is "OpenGL ES-CM major.minor"
+ // OpenGL ES Full profile: The beginning of the returned string is "OpenGL ES major.minor"
+ // Desktop OpenGL: The beginning of the returned string is "major.minor"
+
+ if (!parseVersionString(version, "OpenGL ES-CL ", m_settings.majorVersion, m_settings.minorVersion) &&
+ !parseVersionString(version, "OpenGL ES-CM ", m_settings.majorVersion, m_settings.minorVersion) &&
+ !parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) &&
+ !parseVersionString(version, "", m_settings.majorVersion, m_settings.minorVersion))
+ {
+ err() << "Unable to parse OpenGL version string: \"" << version << "\", defaulting to 1.1" << std::endl;
+ }
}
else
{
- // Can't get the version number, assume 1.1
- m_settings.majorVersion = 1;
- m_settings.minorVersion = 1;
+ err() << "Unable to retrieve OpenGL version string, defaulting to 1.1" << std::endl;
}
}
diff --git a/src/SFML/Window/GlContext.hpp b/src/SFML/Window/GlContext.hpp
index 22efa62..0b66965 100644
--- a/src/SFML/Window/GlContext.hpp
+++ b/src/SFML/Window/GlContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,7 @@
#include <SFML/Config.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/ContextSettings.hpp>
+#include <SFML/Window/GlResource.hpp>
#include <SFML/System/NonCopyable.hpp>
@@ -70,6 +71,19 @@ public:
static void cleanupResource();
////////////////////////////////////////////////////////////
+ /// \brief Register a function to be called when a context is destroyed
+ ///
+ /// This is used for internal purposes in order to properly
+ /// clean up OpenGL resources that cannot be shared bwteen
+ /// contexts.
+ ///
+ /// \param callback Function to be called when a context is destroyed
+ /// \param arg Argument to pass when calling the function
+ ///
+ ////////////////////////////////////////////////////////////
+ static void registerContextDestroyCallback(ContextDestroyCallback callback, void* arg);
+
+ ////////////////////////////////////////////////////////////
/// \brief Acquires a context for short-term use on the current thread
///
////////////////////////////////////////////////////////////
@@ -144,6 +158,17 @@ public:
static GlFunctionPointer getFunction(const char* name);
////////////////////////////////////////////////////////////
+ /// \brief Get the currently active context's ID
+ ///
+ /// The context ID is used to identify contexts when
+ /// managing unshareable OpenGL resources.
+ ///
+ /// \return The active context's ID or 0 if no context is currently active
+ ///
+ ////////////////////////////////////////////////////////////
+ static Uint64 getActiveContextId();
+
+ ////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
@@ -218,6 +243,12 @@ protected:
virtual bool makeCurrent(bool current) = 0;
////////////////////////////////////////////////////////////
+ /// \brief Notify unshared GlResources of context destruction
+ ///
+ ////////////////////////////////////////////////////////////
+ void cleanupUnsharedResources();
+
+ ////////////////////////////////////////////////////////////
/// \brief Evaluate a pixel format configuration
///
/// This functions can be used by implementations that have
@@ -259,6 +290,11 @@ private:
///
////////////////////////////////////////////////////////////
void checkSettings(const ContextSettings& requestedSettings);
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ const Uint64 m_id; ///< Unique number that identifies the context
};
} // namespace priv
diff --git a/src/SFML/Window/GlResource.cpp b/src/SFML/Window/GlResource.cpp
index 546ed35..64fc88c 100644
--- a/src/SFML/Window/GlResource.cpp
+++ b/src/SFML/Window/GlResource.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -46,19 +46,15 @@ GlResource::~GlResource()
////////////////////////////////////////////////////////////
-void GlResource::ensureGlContext()
+void GlResource::registerContextDestroyCallback(ContextDestroyCallback callback, void* arg)
{
- // Empty function for ABI compatibility, use TransientContextLock instead
+ priv::GlContext::registerContextDestroyCallback(callback, arg);
}
////////////////////////////////////////////////////////////
-GlResource::TransientContextLock::TransientContextLock() :
-m_context(0)
+GlResource::TransientContextLock::TransientContextLock()
{
- // m_context is no longer used
- // Remove it when ABI can be broken
-
priv::GlContext::acquireTransientContext();
}
diff --git a/src/SFML/Window/InputImpl.hpp b/src/SFML/Window/InputImpl.hpp
index 279b3c6..305fc09 100644
--- a/src/SFML/Window/InputImpl.hpp
+++ b/src/SFML/Window/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -32,7 +32,7 @@
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/InputImpl.hpp>
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
#include <SFML/Window/Unix/InputImpl.hpp>
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/InputImpl.hpp>
diff --git a/src/SFML/Window/Joystick.cpp b/src/SFML/Window/Joystick.cpp
index 9d5c69f..62793f1 100644
--- a/src/SFML/Window/Joystick.cpp
+++ b/src/SFML/Window/Joystick.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/JoystickImpl.hpp b/src/SFML/Window/JoystickImpl.hpp
index 1806396..e4fd7e2 100644
--- a/src/SFML/Window/JoystickImpl.hpp
+++ b/src/SFML/Window/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -90,6 +90,10 @@ struct JoystickState
#include <SFML/Window/FreeBSD/JoystickImpl.hpp>
+#elif defined(SFML_SYSTEM_OPENBSD)
+
+ #include <SFML/Window/OpenBSD/JoystickImpl.hpp>
+
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/JoystickImpl.hpp>
diff --git a/src/SFML/Window/JoystickManager.cpp b/src/SFML/Window/JoystickManager.cpp
index b89a747..1574faa 100644
--- a/src/SFML/Window/JoystickManager.cpp
+++ b/src/SFML/Window/JoystickManager.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/JoystickManager.hpp b/src/SFML/Window/JoystickManager.hpp
index 2ccfa61..08692cd 100644
--- a/src/SFML/Window/JoystickManager.hpp
+++ b/src/SFML/Window/JoystickManager.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Keyboard.cpp b/src/SFML/Window/Keyboard.cpp
index 264d33f..14cda19 100644
--- a/src/SFML/Window/Keyboard.cpp
+++ b/src/SFML/Window/Keyboard.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Mouse.cpp b/src/SFML/Window/Mouse.cpp
index bbc5b79..862dc69 100644
--- a/src/SFML/Window/Mouse.cpp
+++ b/src/SFML/Window/Mouse.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h b/src/SFML/Window/OSX/AutoreleasePoolWrapper.h
index 6fedaaf..020fa22 100644
--- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h
+++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
index 9f832c7..6b341b2 100644
--- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
+++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/ClipboardImpl.hpp b/src/SFML/Window/OSX/ClipboardImpl.hpp
new file mode 100644
index 0000000..d3aabef
--- /dev/null
+++ b/src/SFML/Window/OSX/ClipboardImpl.hpp
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPLCOCOA_HPP
+#define SFML_CLIPBOARDIMPLCOCOA_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class ClipboardImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String object containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARDIMPLCOCOA_HPP
+
diff --git a/src/SFML/Window/OSX/ClipboardImpl.mm b/src/SFML/Window/OSX/ClipboardImpl.mm
new file mode 100644
index 0000000..a14d871
--- /dev/null
+++ b/src/SFML/Window/OSX/ClipboardImpl.mm
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/OSX/ClipboardImpl.hpp>
+
+#import <AppKit/AppKit.h>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getString()
+{
+ NSPasteboard* pboard = [NSPasteboard generalPasteboard];
+ NSString* data = [pboard stringForType:NSPasteboardTypeString];
+
+ char const* utf8 = [data cStringUsingEncoding:NSUTF8StringEncoding];
+ NSUInteger length = [data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+
+ return String::fromUtf8(utf8, utf8 + length);
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ std::basic_string<Uint8> utf8 = text.toUtf8();
+ NSString* data = [[NSString alloc] initWithBytes:utf8.data()
+ length:utf8.length()
+ encoding:NSUTF8StringEncoding];
+
+ NSPasteboard* pboard = [NSPasteboard generalPasteboard];
+ [pboard declareTypes:@[NSPasteboardTypeString] owner:nil];
+ [pboard setString:data forType:NSPasteboardTypeString];
+
+ [data release];
+}
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/OSX/CursorImpl.hpp b/src/SFML/Window/OSX/CursorImpl.hpp
new file mode 100644
index 0000000..43af792
--- /dev/null
+++ b/src/SFML/Window/OSX/CursorImpl.hpp
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
+// Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPLOSX_HPP
+#define SFML_CURSORIMPLOSX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+
+////////////////////////////////////////////////////////////
+// Predefine OBJ-C classes
+////////////////////////////////////////////////////////////
+#ifdef __OBJC__
+
+@class NSCursor;
+typedef NSCursor* NSCursorRef;
+
+#else // If C++
+
+typedef void* NSCursorRef;
+
+#endif
+
+namespace sf
+{
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Mac OS X implementation of Cursor
+///
+////////////////////////////////////////////////////////////
+class CursorImpl : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Refer to sf::Cursor::Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// Refer to sf::Cursor::~Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ ~CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// Refer to sf::Cursor::loadFromPixels().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Refer to sf::Cursor::loadFromSystem().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Cursor::Type type);
+
+private:
+
+ friend class WindowImplCocoa;
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ NSCursorRef m_cursor; ///< System cursor handle
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_CURSORIMPLOSX_HPP
diff --git a/src/SFML/Window/OSX/CursorImpl.mm b/src/SFML/Window/OSX/CursorImpl.mm
new file mode 100644
index 0000000..5f41376
--- /dev/null
+++ b/src/SFML/Window/OSX/CursorImpl.mm
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
+// Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/OSX/CursorImpl.hpp>
+
+#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
+#import <SFML/Window/OSX/NSImage+raw.h>
+#import <AppKit/AppKit.h>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+CursorImpl::CursorImpl() :
+m_cursor(nil)
+{
+ // Just ask for a pool
+ ensureThreadHasPool();
+}
+
+
+////////////////////////////////////////////////////////////
+CursorImpl::~CursorImpl()
+{
+ [m_cursor release];
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ NSSize nssize = NSMakeSize(size.x, size.y);
+ NSImage* image = [NSImage imageWithRawData:pixels andSize:nssize];
+ NSPoint nshotspot = NSMakePoint(hotspot.x, hotspot.y);
+
+ m_cursor = [[NSCursor alloc] initWithImage:image hotSpot:nshotspot];
+
+ return m_cursor != nil;
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromSystem(Cursor::Type type)
+{
+ switch (type)
+ {
+ default: return false;
+
+ case Cursor::Arrow: m_cursor = [NSCursor arrowCursor]; break;
+ case Cursor::Text: m_cursor = [NSCursor IBeamCursor]; break;
+ case Cursor::Hand: m_cursor = [NSCursor pointingHandCursor]; break;
+ case Cursor::SizeHorizontal: m_cursor = [NSCursor resizeLeftRightCursor]; break;
+ case Cursor::SizeVertical: m_cursor = [NSCursor resizeUpDownCursor]; break;
+ case Cursor::Cross: m_cursor = [NSCursor crosshairCursor]; break;
+ case Cursor::NotAllowed: m_cursor = [NSCursor operationNotAllowedCursor]; break;
+ }
+
+ // Since we didn't allocate the cursor ourself, we have to retain it
+ // in order to not break the retain count.
+ [m_cursor retain];
+
+ // For all non-default cases, it was a success.
+ return true;
+}
+
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp
index 819039a..388d008 100644
--- a/src/SFML/Window/OSX/HIDInputManager.hpp
+++ b/src/SFML/Window/OSX/HIDInputManager.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm
index c74200c..a332932 100644
--- a/src/SFML/Window/OSX/HIDInputManager.mm
+++ b/src/SFML/Window/OSX/HIDInputManager.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -152,6 +152,7 @@ void HIDInputManager::initializeKeyboard()
CFSetRef keyboards = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
if (keyboards == NULL)
{
+ sf::err() << "No keyboard detected by the HID manager!" << std::endl;
freeUp();
return;
}
@@ -313,9 +314,11 @@ void HIDInputManager::freeUp()
if (m_layoutData != 0)
CFRelease(m_layoutData);
+ m_layoutData = 0;
// Do not release m_layout! It is owned by m_layoutData.
if (m_manager != 0)
CFRelease(m_manager);
+ m_manager = 0;
for (unsigned int i = 0; i < Keyboard::KeyCount; ++i)
{
@@ -355,11 +358,8 @@ CFSetRef HIDInputManager::copyDevices(UInt32 page, UInt32 usage)
bool HIDInputManager::isPressed(IOHIDElements& elements)
{
- if (!m_isValid)
- {
- sf::err() << "HIDInputManager is invalid." << std::endl;
+ if (!m_isValid)
return false;
- }
// state = true if at least one corresponding HID button is pressed
bool state = false;
@@ -694,7 +694,7 @@ Keyboard::Key HIDInputManager::localizedKeys(UniChar ch)
////////////////////////////////////////////////////////
Keyboard::Key HIDInputManager::nonLocalizedKeys(UniChar virtualKeycode)
{
- // (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577
+ // (Some) 0x code based on https://forums.macrumors.com/showthread.php?t=780577
// Some sf::Keyboard::Key are present twice.
switch (virtualKeycode)
{
@@ -755,13 +755,13 @@ Keyboard::Key HIDInputManager::nonLocalizedKeys(UniChar virtualKeycode)
case 0x21: return sf::Keyboard::LBracket;
case 0x1e: return sf::Keyboard::RBracket;
- case 0x29: return sf::Keyboard::SemiColon;
+ case 0x29: return sf::Keyboard::Semicolon;
case 0x2b: return sf::Keyboard::Comma;
case 0x41: /* keypad */ return sf::Keyboard::Period;
case 0x2f: /* keyboard */ return sf::Keyboard::Period;
case 0x27: return sf::Keyboard::Quote;
case 0x2c: return sf::Keyboard::Slash;
- case 0x2a: return sf::Keyboard::BackSlash;
+ case 0x2a: return sf::Keyboard::Backslash;
// sf::Keyboard::Tilde might be in conflict with some other key.
// 0x0a is for "Non-US Backslash" according to HID Calibrator,
@@ -770,11 +770,11 @@ Keyboard::Key HIDInputManager::nonLocalizedKeys(UniChar virtualKeycode)
case 0x51: /* keypad */ return sf::Keyboard::Equal;
case 0x18: /* keyboard */ return sf::Keyboard::Equal;
- case 0x32: return sf::Keyboard::Dash;
+ case 0x32: return sf::Keyboard::Hyphen;
case 0x31: return sf::Keyboard::Space;
- case 0x4c: /* keypad */ return sf::Keyboard::Return;
- case 0x24: /* keyboard */ return sf::Keyboard::Return;
- case 0x33: return sf::Keyboard::BackSpace;
+ case 0x4c: /* keypad */ return sf::Keyboard::Enter;
+ case 0x24: /* keyboard */ return sf::Keyboard::Enter;
+ case 0x33: return sf::Keyboard::Backspace;
case 0x30: return sf::Keyboard::Tab;
// Duplicates (see next section).
diff --git a/src/SFML/Window/OSX/HIDJoystickManager.cpp b/src/SFML/Window/OSX/HIDJoystickManager.cpp
index 6441680..72c165a 100644
--- a/src/SFML/Window/OSX/HIDJoystickManager.cpp
+++ b/src/SFML/Window/OSX/HIDJoystickManager.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/HIDJoystickManager.hpp b/src/SFML/Window/OSX/HIDJoystickManager.hpp
index 6052d38..eb249cc 100644
--- a/src/SFML/Window/OSX/HIDJoystickManager.hpp
+++ b/src/SFML/Window/OSX/HIDJoystickManager.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/InputImpl.hpp b/src/SFML/Window/OSX/InputImpl.hpp
index 8055d42..6f874bc 100644
--- a/src/SFML/Window/OSX/InputImpl.hpp
+++ b/src/SFML/Window/OSX/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/InputImpl.mm b/src/SFML/Window/OSX/InputImpl.mm
index cf41b03..361e1be 100644
--- a/src/SFML/Window/OSX/InputImpl.mm
+++ b/src/SFML/Window/OSX/InputImpl.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/JoystickImpl.cpp b/src/SFML/Window/OSX/JoystickImpl.cpp
index 215a6a9..9552b19 100644
--- a/src/SFML/Window/OSX/JoystickImpl.cpp
+++ b/src/SFML/Window/OSX/JoystickImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -147,19 +147,16 @@ bool JoystickImpl::isConnected(unsigned int index)
// If there exists a device d s.t. there is no j s.t.
// m_locationIDs[j] == d's location then we have a new device.
- for (CFIndex didx(0); didx < size; ++didx)
+ for (CFIndex didx(0); !state && didx < size; ++didx)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx];
Location dloc = HIDInputManager::getLocationID(d);
bool foundJ = false;
- for (unsigned int j(0); j < Joystick::Count; ++j)
+ for (unsigned int j(0); !foundJ && j < Joystick::Count; ++j)
{
if (m_locationIDs[j] == dloc)
- {
foundJ = true;
- break; // no need to loop again
- }
}
if (!foundJ) {
@@ -167,7 +164,6 @@ bool JoystickImpl::isConnected(unsigned int index)
// We set it up for Open(..)
m_locationIDs[index] = dloc;
state = true;
- break; // We stop looking for a new device
}
}
}
@@ -185,6 +181,7 @@ bool JoystickImpl::isConnected(unsigned int index)
bool JoystickImpl::open(unsigned int index)
{
m_index = index;
+ m_hat = NULL;
Location deviceLoc = m_locationIDs[index]; // The device we need to load
// Get all devices
@@ -199,19 +196,15 @@ bool JoystickImpl::open(unsigned int index)
// Get the desired joystick.
IOHIDDeviceRef self = 0;
- for (CFIndex i(0); i < joysticksCount; ++i)
+ for (CFIndex i(0); self == 0 && i < joysticksCount; ++i)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
if (deviceLoc == HIDInputManager::getLocationID(d))
- {
self = d;
- break; // We found it so we stop looping.
- }
}
if (self == 0)
{
- // This shouldn't happen!
CFRelease(devices);
return false;
}
@@ -229,24 +222,14 @@ bool JoystickImpl::open(unsigned int index)
return false;
}
- // How many elements are there?
- CFIndex elementsCount = CFArrayGetCount(elements);
-
- if (elementsCount == 0)
- {
- // What is a joystick with no element?
- CFRelease(elements);
- CFRelease(devices);
- return false;
- }
-
// Go through all connected elements.
+ CFIndex elementsCount = CFArrayGetCount(elements);
for (int i = 0; i < elementsCount; ++i)
{
IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
- switch (IOHIDElementGetType(element))
+ switch (IOHIDElementGetUsagePage(element))
{
- case kIOHIDElementTypeInput_Misc:
+ case kHIDPage_GenericDesktop:
switch (IOHIDElementGetUsage(element))
{
case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break;
@@ -255,19 +238,64 @@ bool JoystickImpl::open(unsigned int index)
case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break;
case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break;
case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break;
- default: break;
- // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored.
+
+ case kHIDUsage_GD_Hatswitch:
+ // From §4.3 MiscellaneousControls of HUT v1.12:
+ //
+ // > Hat Switch:
+ // > A typical example is four switches that are capable of generating
+ // > information about four possible directions in which the knob can be
+ // > tilted. Intermediate positions can also be decoded if the hardware
+ // > allows two switches to be reported simultaneously.
+ //
+ // We assume this model here as well. Hence, with 4 switches and intermediate
+ // positions we have 8 values (0-7) plus the "null" state (8).
+ {
+ CFIndex min = IOHIDElementGetLogicalMin(element);
+ CFIndex max = IOHIDElementGetLogicalMax(element);
+
+ if (min != 0 || max != 7)
+ {
+ sf::err() << std::hex
+ << "Joystick (vendor/product id: 0x" << m_identification.vendorId
+ << "/0x" << m_identification.productId << std::dec
+ << ") range is an unexpected one: [" << min << ", " << max << "]"
+ << std::endl;
+ }
+ else
+ {
+ m_hat = element;
+ }
+ }
+ break;
+
+ case kHIDUsage_GD_GamePad:
+ // We assume a game pad is an application collection, meaning it doesn't hold
+ // any values per say. They kind of "emit" the joystick's usages.
+ // See §3.4.3 Usage Types (Collection) of HUT v1.12
+ if (IOHIDElementGetCollectionType(element) != kIOHIDElementCollectionTypeApplication)
+ {
+ sf::err() << std::hex << "Gamepage (vendor/product id: 0x" << m_identification.vendorId
+ << "/0x" << m_identification.productId << ") is not an CA but a 0x"
+ << IOHIDElementGetCollectionType(element) << std::dec << std::endl;
+ }
+ break;
+
+ default:
+#ifdef SFML_DEBUG
+ sf::err() << "Unexpected usage for element of Page Generic Desktop: 0x" << std::hex << IOHIDElementGetUsage(element) << std::dec << std::endl;
+#endif
+ break;
}
break;
- case kIOHIDElementTypeInput_Button:
+ case kHIDPage_Button:
if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot...
m_buttons.push_back(element); // ...we add this element to the list
// Else: too many buttons. We ignore this one.
break;
- default: // Make compiler happy
- break;
+ default: /* No other page is expected because of the mask applied by the HID manager. */ break;
}
}
@@ -275,17 +303,16 @@ bool JoystickImpl::open(unsigned int index)
// HID Usage (assigned by manufacturer and/or a driver).
std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate);
- // Note: Joy::AxisPovX/Y are not supported (yet).
- // Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test.
-
// Retain all these objects for personal use
for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it)
CFRetain(*it);
for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it)
CFRetain(it->second);
+ if (m_hat != NULL)
+ CFRetain(m_hat);
// Note: we didn't retain element in the switch because we might have multiple
- // Axis X (for example) and we want to keep only the last one. So to prevent
+ // Axis X (for example) and we want to keep only the last one. To prevent
// leaking we retain objects 'only' now.
CFRelease(devices);
@@ -306,6 +333,10 @@ void JoystickImpl::close()
CFRelease(it->second);
m_axis.clear();
+ if (m_hat != NULL)
+ CFRelease(m_hat);
+ m_hat = NULL;
+
// And we unregister this joystick
m_locationIDs[m_index] = 0;
}
@@ -320,9 +351,11 @@ JoystickCaps JoystickImpl::getCapabilities() const
caps.buttonCount = m_buttons.size();
// Axis:
- for (AxisMap::const_iterator it(m_axis.begin()); it != m_axis.end(); ++it) {
+ for (AxisMap::const_iterator it(m_axis.begin()); it != m_axis.end(); ++it)
caps.axes[it->first] = true;
- }
+
+ if (m_hat != NULL)
+ caps.axes[Joystick::PovX] = caps.axes[Joystick::PovY] = true;
return caps;
}
@@ -339,7 +372,7 @@ Joystick::Identification JoystickImpl::getIdentification() const
JoystickState JoystickImpl::update()
{
static const JoystickState disconnectedState; // return this if joystick was disconnected
- JoystickState state; // otherwise return that
+ JoystickState state; // otherwise return that
state.connected = true;
// Note: free up is done in close() which is called, if required,
@@ -360,14 +393,11 @@ JoystickState JoystickImpl::update()
// Search for it
bool found = false;
- for (CFIndex i(0); i < joysticksCount; ++i)
+ for (CFIndex i(0); !found && i < joysticksCount; ++i)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
if (selfLoc == HIDInputManager::getLocationID(d))
- {
found = true;
- break; // Stop looping
- }
}
// Release unused stuff
@@ -387,7 +417,6 @@ JoystickState JoystickImpl::update()
// Check for plug out.
if (!value)
{
- // No value? Hum... Seems like the joystick is gone
return disconnectedState;
}
@@ -404,7 +433,6 @@ JoystickState JoystickImpl::update()
// Check for plug out.
if (!value)
{
- // No value? Hum... Seems like the joystick is gone
return disconnectedState;
}
@@ -427,9 +455,70 @@ JoystickState JoystickImpl::update()
state.axes[it->first] = scaledValue;
}
+ // Update POV/Hat state. Assuming model described in `open`, values are:
+ //
+ // North-West / 7 North / 0 North-East / 1
+ // West / 6 Null / 8 East / 2
+ // South-West / 5 South / 4 South-East / 3
+ //
+ if (m_hat != NULL)
+ {
+ IOHIDValueRef value = 0;
+ IOHIDDeviceGetValue(IOHIDElementGetDevice(m_hat), m_hat, &value);
+
+ // Check for plug out.
+ if (!value)
+ {
+ return disconnectedState;
+ }
+
+ CFIndex raw = IOHIDValueGetIntegerValue(value);
+
+ // Load PovX
+ switch (raw)
+ {
+ case 1:
+ case 2:
+ case 3:
+ state.axes[Joystick::PovX] = +100;
+ break;
+
+ case 5:
+ case 6:
+ case 7:
+ state.axes[Joystick::PovX] = -100;
+ break;
+
+ default:
+ state.axes[Joystick::PovX] = 0;
+ break;
+ }
+
+ // Load PovY
+ switch (raw)
+ {
+ case 0:
+ case 1:
+ case 7:
+ state.axes[Joystick::PovY] = +100;
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ state.axes[Joystick::PovY] = -100;
+ break;
+
+ default:
+ state.axes[Joystick::PovY] = 0;
+ break;
+ }
+ }
+
return state;
}
} // namespace priv
} // namespace sf
+
diff --git a/src/SFML/Window/OSX/JoystickImpl.hpp b/src/SFML/Window/OSX/JoystickImpl.hpp
index 9d185cb..f4ad680 100644
--- a/src/SFML/Window/OSX/JoystickImpl.hpp
+++ b/src/SFML/Window/OSX/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -120,8 +120,9 @@ private:
typedef std::map<sf::Joystick::Axis, IOHIDElementRef> AxisMap;
typedef std::vector<IOHIDElementRef> ButtonsVector;
- AxisMap m_axis; ///< Axis (IOHIDElementRef) connected to the joystick
- ButtonsVector m_buttons; ///< Buttons (IOHIDElementRef) connected to the joystick
+ AxisMap m_axis; ///< Axes (but not POV/Hat) of the joystick
+ IOHIDElementRef m_hat; ///< POV/Hat axis of the joystick
+ ButtonsVector m_buttons; ///< Buttons of the joystick
unsigned int m_index; ///< SFML index
Joystick::Identification m_identification; ///< Joystick identification
diff --git a/src/SFML/Window/OSX/NSImage+raw.h b/src/SFML/Window/OSX/NSImage+raw.h
index 6672ea8..99e0484 100644
--- a/src/SFML/Window/OSX/NSImage+raw.h
+++ b/src/SFML/Window/OSX/NSImage+raw.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/NSImage+raw.mm b/src/SFML/Window/OSX/NSImage+raw.mm
index ea33a16..56ee6c9 100644
--- a/src/SFML/Window/OSX/NSImage+raw.mm
+++ b/src/SFML/Window/OSX/NSImage+raw.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFApplication.h b/src/SFML/Window/OSX/SFApplication.h
index 8b28016..5f2071f 100644
--- a/src/SFML/Window/OSX/SFApplication.h
+++ b/src/SFML/Window/OSX/SFApplication.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFApplication.m b/src/SFML/Window/OSX/SFApplication.m
index 90928cb..a922543 100644
--- a/src/SFML/Window/OSX/SFApplication.m
+++ b/src/SFML/Window/OSX/SFApplication.m
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFApplicationDelegate.h b/src/SFML/Window/OSX/SFApplicationDelegate.h
index 9b87b2b..542c0a1 100644
--- a/src/SFML/Window/OSX/SFApplicationDelegate.h
+++ b/src/SFML/Window/OSX/SFApplicationDelegate.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFApplicationDelegate.m b/src/SFML/Window/OSX/SFApplicationDelegate.m
index 7583411..d7e6050 100644
--- a/src/SFML/Window/OSX/SFApplicationDelegate.m
+++ b/src/SFML/Window/OSX/SFApplicationDelegate.m
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFContext.hpp b/src/SFML/Window/OSX/SFContext.hpp
index 8f020b3..5fa3b21 100644
--- a/src/SFML/Window/OSX/SFContext.hpp
+++ b/src/SFML/Window/OSX/SFContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFContext.mm b/src/SFML/Window/OSX/SFContext.mm
index 8c7e5a1..cf74de9 100644
--- a/src/SFML/Window/OSX/SFContext.mm
+++ b/src/SFML/Window/OSX/SFContext.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -103,6 +103,9 @@ m_window(0)
////////////////////////////////////////////////////////////
SFContext::~SFContext()
{
+ // Notify unshared OpenGL resources of context destruction
+ cleanupUnsharedResources();
+
[m_context clearDrawable];
if (m_context == [NSOpenGLContext currentContext])
diff --git a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h
index daaa72d..ee2ef66 100644
--- a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h
+++ b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm
index eec7e20..763f2ca 100644
--- a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm
+++ b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm
index aab4d9b..907de16 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm
+++ b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h b/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h
index 0ed9aaf..6003c00 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h
+++ b/src/SFML/Window/OSX/SFOpenGLView+keyboard_priv.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse.mm b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
index fa65aa6..4b23042 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
+++ b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -41,6 +41,25 @@
@implementation SFOpenGLView (mouse)
////////////////////////////////////////////////////////
+-(void)setCursor:(NSCursor*)cursor
+{
+ m_cursor = cursor;
+
+ // indirect call to resetCursorRects to set the cursor
+ [self.window invalidateCursorRectsForView:self];
+}
+
+
+////////////////////////////////////////////////////////
+-(void)resetCursorRects
+{
+ // addCursorRect:cursor: has to be called from within this function!
+ [self addCursorRect:[self frame] cursor:m_cursor];
+ [m_cursor setOnMouseEntered:YES];
+}
+
+
+////////////////////////////////////////////////////////
-(BOOL)isMouseInside
{
NSPoint relativeToWindow = [[self window] mouseLocationOutsideOfEventStream];
diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
index a896e45..6f509ad 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
+++ b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFOpenGLView.h b/src/SFML/Window/OSX/SFOpenGLView.h
index d25b1b2..7444ff7 100644
--- a/src/SFML/Window/OSX/SFOpenGLView.h
+++ b/src/SFML/Window/OSX/SFOpenGLView.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -71,6 +71,7 @@ namespace sf {
sf::priv::WindowImplCocoa* m_requester; ///< View's requester
BOOL m_useKeyRepeat; ///< Key repeat setting
BOOL m_mouseIsIn; ///< Mouse positional state
+ NSCursor* m_cursor; ///< Active cursor
NSTrackingArea* m_trackingArea; ///< Mouse tracking area
BOOL m_fullscreen; ///< Indicate whether the window is fullscreen or not
CGFloat m_scaleFactor; ///< Display scale factor (e.g. 1x for classic display, 2x for retina)
@@ -155,6 +156,12 @@ namespace sf {
@interface SFOpenGLView (mouse)
////////////////////////////////////////////////////////////
+/// \brief Set the system cursor for the window area
+///
+////////////////////////////////////////////////////////////
+-(void)setCursor:(NSCursor*)cursor;
+
+////////////////////////////////////////////////////////////
/// \brief Compute the position of the cursor
///
/// \param eventOrNil if nil the cursor position is the current one
diff --git a/src/SFML/Window/OSX/SFOpenGLView.mm b/src/SFML/Window/OSX/SFOpenGLView.mm
index aa51de1..e8fca84 100644
--- a/src/SFML/Window/OSX/SFOpenGLView.mm
+++ b/src/SFML/Window/OSX/SFOpenGLView.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -111,6 +111,7 @@
m_cursorGrabbed = NO;
m_deltaXBuffer = 0;
m_deltaYBuffer = 0;
+ m_cursor = [NSCursor arrowCursor];
// Create a hidden text view for parsing key down event properly
m_silentResponder = [[SFSilentResponder alloc] init];
diff --git a/src/SFML/Window/OSX/SFSilentResponder.h b/src/SFML/Window/OSX/SFSilentResponder.h
index 6c6da5d..a9f9b7c 100644
--- a/src/SFML/Window/OSX/SFSilentResponder.h
+++ b/src/SFML/Window/OSX/SFSilentResponder.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFSilentResponder.m b/src/SFML/Window/OSX/SFSilentResponder.m
index 00569bf..feb5783 100644
--- a/src/SFML/Window/OSX/SFSilentResponder.m
+++ b/src/SFML/Window/OSX/SFSilentResponder.m
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFViewController.h b/src/SFML/Window/OSX/SFViewController.h
index 721d013..69dc7a3 100644
--- a/src/SFML/Window/OSX/SFViewController.h
+++ b/src/SFML/Window/OSX/SFViewController.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm
index 03b161f..c92283b 100644
--- a/src/SFML/Window/OSX/SFViewController.mm
+++ b/src/SFML/Window/OSX/SFViewController.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -128,6 +128,13 @@
}
+////////////////////////////////////////////////////////
+-(void)setCursor:(NSCursor*)cursor
+{
+ return [m_oglView setCursor:cursor];
+}
+
+
////////////////////////////////////////////////////////////
-(NSPoint)position
{
@@ -247,7 +254,7 @@
if ([NSThread currentThread] != [NSThread mainThread])
{
/*
- * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
+ * See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information.
*/
sf::err() << "Cannot fetch event from a worker thread. (OS X restriction)" << std::endl;
diff --git a/src/SFML/Window/OSX/SFWindow.h b/src/SFML/Window/OSX/SFWindow.h
index c24f373..1d35245 100644
--- a/src/SFML/Window/OSX/SFWindow.h
+++ b/src/SFML/Window/OSX/SFWindow.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -40,7 +40,7 @@
/// acceptsFirstResponder and canBecomeKeyWindow messages must
/// return YES to grab fullscreen events.
///
-/// See http://stackoverflow.com/questions/999464/fullscreen-key-down-actions
+/// See https://stackoverflow.com/questions/999464/fullscreen-key-down-actions
///
/// \return YES
///
diff --git a/src/SFML/Window/OSX/SFWindow.m b/src/SFML/Window/OSX/SFWindow.m
index 38c95e4..087f990 100644
--- a/src/SFML/Window/OSX/SFWindow.m
+++ b/src/SFML/Window/OSX/SFWindow.m
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -93,7 +93,7 @@
////////////////////////////////////////////////////////
-(BOOL)validateMenuItem:(NSMenuItem*)menuItem
{
- return [menuItem action] == @selector(performClose:);
+ return [menuItem action] == @selector(performClose:) || [super validateMenuItem:menuItem];
}
diff --git a/src/SFML/Window/OSX/SFWindowController.h b/src/SFML/Window/OSX/SFWindowController.h
index 7c7635f..df0585b 100644
--- a/src/SFML/Window/OSX/SFWindowController.h
+++ b/src/SFML/Window/OSX/SFWindowController.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm
index b12db9b..186a0fb 100644
--- a/src/SFML/Window/OSX/SFWindowController.mm
+++ b/src/SFML/Window/OSX/SFWindowController.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -136,7 +136,7 @@
if ([NSThread currentThread] != [NSThread mainThread])
{
/*
- * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
+ * See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information.
*/
sf::err() << "Cannot create a window from a worker thread. (OS X limitation)" << std::endl;
@@ -371,6 +371,13 @@
}
+////////////////////////////////////////////////////////
+-(void)setCursor:(NSCursor*)cursor
+{
+ return [m_oglView setCursor:cursor];
+}
+
+
////////////////////////////////////////////////////////////
-(NSPoint)position
{
@@ -559,7 +566,7 @@
if ([NSThread currentThread] != [NSThread mainThread])
{
/*
- * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
+ * See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information.
*/
sf::err() << "Cannot fetch event from a worker thread. (OS X restriction)" << std::endl;
diff --git a/src/SFML/Window/OSX/Scaling.h b/src/SFML/Window/OSX/Scaling.h
index 733812d..62f13ae 100644
--- a/src/SFML/Window/OSX/Scaling.h
+++ b/src/SFML/Window/OSX/Scaling.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/SensorImpl.cpp b/src/SFML/Window/OSX/SensorImpl.cpp
index 4c00668..3496265 100644
--- a/src/SFML/Window/OSX/SensorImpl.cpp
+++ b/src/SFML/Window/OSX/SensorImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/OSX/SensorImpl.hpp b/src/SFML/Window/OSX/SensorImpl.hpp
index 09bfd23..fe81b8d 100644
--- a/src/SFML/Window/OSX/SensorImpl.hpp
+++ b/src/SFML/Window/OSX/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/OSX/VideoModeImpl.cpp b/src/SFML/Window/OSX/VideoModeImpl.cpp
index ae5fdfb..efd5e46 100644
--- a/src/SFML/Window/OSX/VideoModeImpl.cpp
+++ b/src/SFML/Window/OSX/VideoModeImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp
index 8daa8f8..eea318d 100644
--- a/src/SFML/Window/OSX/WindowImplCocoa.hpp
+++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -322,6 +322,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm
index b294881..edb6935 100644
--- a/src/SFML/Window/OSX/WindowImplCocoa.mm
+++ b/src/SFML/Window/OSX/WindowImplCocoa.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -494,6 +494,13 @@ void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed)
////////////////////////////////////////////////////////////
+void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor)
+{
+ [m_delegate setCursor:cursor.m_cursor];
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
{
if (enabled)
diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h
index 0ca8562..d6cfa90 100644
--- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h
+++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
@@ -105,6 +105,12 @@ namespace sf {
-(void)setCursorGrabbed:(BOOL)grabbed;
////////////////////////////////////////////////////////////
+/// \brief Set the system cursor for the window area
+///
+////////////////////////////////////////////////////////////
+-(void)setCursor:(NSCursor*)cursor;
+
+////////////////////////////////////////////////////////////
/// \brief Get window position
///
/// \return Top left corner of the window or view
diff --git a/src/SFML/Window/OSX/cg_sf_conversion.hpp b/src/SFML/Window/OSX/cg_sf_conversion.hpp
index 3d18d6f..c928dd9 100644
--- a/src/SFML/Window/OSX/cg_sf_conversion.hpp
+++ b/src/SFML/Window/OSX/cg_sf_conversion.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/cg_sf_conversion.mm b/src/SFML/Window/OSX/cg_sf_conversion.mm
index df0cfc4..5d9a53f 100644
--- a/src/SFML/Window/OSX/cg_sf_conversion.mm
+++ b/src/SFML/Window/OSX/cg_sf_conversion.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/cpp_objc_conversion.h b/src/SFML/Window/OSX/cpp_objc_conversion.h
index dce1779..db0d572 100644
--- a/src/SFML/Window/OSX/cpp_objc_conversion.h
+++ b/src/SFML/Window/OSX/cpp_objc_conversion.h
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OSX/cpp_objc_conversion.mm b/src/SFML/Window/OSX/cpp_objc_conversion.mm
index af7894d..0ac4b50 100644
--- a/src/SFML/Window/OSX/cpp_objc_conversion.mm
+++ b/src/SFML/Window/OSX/cpp_objc_conversion.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Marco Antognini (antognini.marco@gmail.com),
+// Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
diff --git a/src/SFML/Window/OpenBSD/JoystickImpl.cpp b/src/SFML/Window/OpenBSD/JoystickImpl.cpp
new file mode 100644
index 0000000..58dfc82
--- /dev/null
+++ b/src/SFML/Window/OpenBSD/JoystickImpl.cpp
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/JoystickImpl.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+void JoystickImpl::initialize()
+{
+ // To implement
+}
+
+
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::cleanup()
+{
+ // To implement
+}
+
+
+////////////////////////////////////////////////////////////
+bool JoystickImpl::isConnected(unsigned int index)
+{
+ // To implement
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool JoystickImpl::open(unsigned int index)
+{
+ // To implement
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::close()
+{
+ // To implement
+}
+
+
+////////////////////////////////////////////////////////////
+JoystickCaps JoystickImpl::getCapabilities() const
+{
+ // To implement
+ return JoystickCaps();
+}
+
+
+////////////////////////////////////////////////////////////
+Joystick::Identification JoystickImpl::getIdentification() const
+{
+ return m_identification;
+}
+
+
+////////////////////////////////////////////////////////////
+JoystickState JoystickImpl::update()
+{
+ // To implement
+ return JoystickState();
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/OpenBSD/JoystickImpl.hpp b/src/SFML/Window/OpenBSD/JoystickImpl.hpp
new file mode 100644
index 0000000..af7ef5c
--- /dev/null
+++ b/src/SFML/Window/OpenBSD/JoystickImpl.hpp
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_JOYSTICKIMPLOPENBSD_HPP
+#define SFML_JOYSTICKIMPLOPENBSD_HPP
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief OpenBSD implementation of joysticks
+///
+////////////////////////////////////////////////////////////
+class JoystickImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Perform the global initialization of the joystick module
+ ///
+ ////////////////////////////////////////////////////////////
+ static void initialize();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Perform the global cleanup of the joystick module
+ ///
+ ////////////////////////////////////////////////////////////
+ static void cleanup();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Check if a joystick is currently connected
+ ///
+ /// \param index Index of the joystick to check
+ ///
+ /// \return True if the joystick is connected, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool isConnected(unsigned int index);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Open the joystick
+ ///
+ /// \param index Index assigned to the joystick
+ ///
+ /// \return True on success, false on failure
+ ///
+ ////////////////////////////////////////////////////////////
+ bool open(unsigned int index);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Close the joystick
+ ///
+ ////////////////////////////////////////////////////////////
+ void close();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the joystick capabilities
+ ///
+ /// \return Joystick capabilities
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickCaps getCapabilities() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the joystick identification
+ ///
+ /// \return Joystick identification
+ ///
+ ////////////////////////////////////////////////////////////
+ Joystick::Identification getIdentification() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the joystick and get its new state
+ ///
+ /// \return Joystick state
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickState update();
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ int m_index; ///< Index of the joystick
+ Joystick::Identification m_identification; ///< Joystick identification
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_JOYSTICKIMPLOPENBSD_HPP
diff --git a/src/SFML/Window/Sensor.cpp b/src/SFML/Window/Sensor.cpp
index 5331bbb..ae37412 100644
--- a/src/SFML/Window/Sensor.cpp
+++ b/src/SFML/Window/Sensor.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/SensorImpl.hpp b/src/SFML/Window/SensorImpl.hpp
index aabf277..a543472 100644
--- a/src/SFML/Window/SensorImpl.hpp
+++ b/src/SFML/Window/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -35,7 +35,7 @@
#include <SFML/Window/Win32/SensorImpl.hpp>
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
#include <SFML/Window/Unix/SensorImpl.hpp>
diff --git a/src/SFML/Window/SensorManager.cpp b/src/SFML/Window/SensorManager.cpp
index 409eace..82665e3 100644
--- a/src/SFML/Window/SensorManager.cpp
+++ b/src/SFML/Window/SensorManager.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/SensorManager.hpp b/src/SFML/Window/SensorManager.hpp
index 08bcea4..2285ad3 100644
--- a/src/SFML/Window/SensorManager.hpp
+++ b/src/SFML/Window/SensorManager.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Touch.cpp b/src/SFML/Window/Touch.cpp
index ecc6600..aa63c72 100644
--- a/src/SFML/Window/Touch.cpp
+++ b/src/SFML/Window/Touch.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/ClipboardImpl.cpp b/src/SFML/Window/Unix/ClipboardImpl.cpp
new file mode 100644
index 0000000..32ef21b
--- /dev/null
+++ b/src/SFML/Window/Unix/ClipboardImpl.cpp
@@ -0,0 +1,261 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Unix/ClipboardImpl.hpp>
+#include <SFML/Window/Unix/Display.hpp>
+#include <SFML/System/String.hpp>
+#include <SFML/System/Sleep.hpp>
+#include <iostream>
+#include <string>
+#include <X11/Xlib.h>
+
+
+namespace
+{
+////////////////////////////////////////////////////////////
+void initClipboard();
+void* hostSelection(void*);
+
+sf::String string;
+
+pthread_mutex_t mutex;
+pthread_t host_thread;
+
+bool is_fail = false;
+bool is_init = false;
+bool is_host = false;
+
+Display* display = NULL;
+Window window = 0;
+
+Atom selection = 0;
+Atom atom_targ = 0;
+Atom atom_text = 0;
+Atom utf8_text = 0;
+int xa_string = 31;
+int xa_atom = 4;
+
+////////////////////////////////////////////////////////////
+void initClipboard()
+{
+ is_init = true;
+
+ display = XOpenDisplay(NULL);
+ int screen = DefaultScreen(display);
+ window = XCreateSimpleWindow(display, RootWindow(display, screen),
+ 0, 0, 1, 1, 0, BlackPixel(display, screen), WhitePixel(display, screen));
+
+ selection = XInternAtom(display, "CLIPBOARD", false);
+ atom_targ = XInternAtom(display, "TARGETS", false);
+ atom_text = XInternAtom(display, "TEXT", false);
+ utf8_text = XInternAtom(display, "UTF8_STRING", true);
+
+ if(utf8_text == None)
+ {
+ std::cerr << "UTF-8 format unavailable on clipboard." << std::endl;
+ utf8_text = xa_string;
+ }
+
+ if(pthread_mutex_init(&mutex, NULL))
+ {
+ is_fail = true;
+ std::cerr << "Unable to initialize mutex. Failed to initialize clipboard." << std::endl;
+ return;
+ }
+
+ if(pthread_create(&host_thread, NULL, hostSelection, NULL))
+ {
+ is_fail = true;
+ std::cerr << "Unable to create host thread. Failed to initialize clipboard." << std::endl;
+ return;
+ }
+}
+
+////////////////////////////////////////////////////////////
+void* hostSelection(void*)
+{
+ while(true)
+ {
+ if(XPending(display) && is_host)
+ {
+ XEvent event;
+
+ pthread_mutex_lock(&mutex);
+ XNextEvent(display, &event);
+ pthread_mutex_unlock(&mutex);
+
+ switch(event.type)
+ {
+ case SelectionClear:
+ {
+ pthread_mutex_lock(&mutex);
+ is_host = false;
+ pthread_mutex_unlock(&mutex);
+
+ break;
+ }
+ case SelectionRequest:
+ {
+ if(event.xselectionrequest.selection == selection)
+ {
+ XSelectionRequestEvent* sel_req_event = &event.xselectionrequest;
+ XSelectionEvent sel_event = {0};
+
+ int result = 0;
+ sel_event.type = SelectionNotify,
+ sel_event.display = sel_req_event->display,
+ sel_event.requestor = sel_req_event->requestor,
+ sel_event.selection = sel_req_event->selection,
+ sel_event.time = sel_req_event->time,
+ sel_event.target = sel_req_event->target,
+ sel_event.property = sel_req_event->property;
+
+ std::basic_string<unsigned char> str = string.toUtf8();
+
+ if(sel_event.target == atom_targ)
+ result = XChangeProperty(sel_event.display, sel_event.requestor,
+ sel_event.property, xa_atom, 32, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&utf8_text), 1);
+ else if(sel_event.target == xa_string || sel_event.target == atom_text)
+ result = XChangeProperty(sel_event.display, sel_event.requestor,
+ sel_event.property, xa_string, 8, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&str[0]), str.size());
+ else if(sel_event.target == utf8_text)
+ result = XChangeProperty(sel_event.display, sel_event.requestor,
+ sel_event.property, utf8_text, 8, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&str[0]), str.size());
+ else
+ sel_event.property = None;
+
+ if((result & 2) == 0)
+ XSendEvent(display, sel_event.requestor, 0, 0,
+ reinterpret_cast<XEvent*>(&sel_event));
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+ else
+ sf::sleep(sf::milliseconds(20));
+ }
+}
+}
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getString()
+{
+ if(!is_init)
+ initClipboard();
+
+ if(is_fail || is_host)
+ return string;
+
+ // Dangerous! Wipes all previous events!
+ XSync(display, true);
+ XConvertSelection(display, selection, utf8_text, atom_text, window, CurrentTime);
+
+ XEvent event;
+
+ pthread_mutex_lock(&mutex);
+ XNextEvent(display, &event);
+ pthread_mutex_unlock(&mutex);
+
+ if(event.type == SelectionNotify)
+ {
+ if(event.xselection.selection != selection || event.xselection.target != utf8_text)
+ {
+ std::cerr << "Failed to convert selection." << std::endl;
+ return string;
+ }
+
+ if(event.xselection.property)
+ {
+ Atom target;
+ int format;
+ unsigned long size;
+ unsigned long byte_left;
+ unsigned char* data;
+
+ XGetWindowProperty(event.xselection.display,
+ event.xselection.requestor, event.xselection.property,
+ 0L, (~0L), false, AnyPropertyType,
+ &target, &format, &size, &byte_left, &data);
+
+ if(target == utf8_text)
+ {
+ std::basic_string<unsigned char> str(data, size);
+ string = sf::String::fromUtf8(str.begin(), str.end());
+
+ XFree(data);
+ }
+
+ XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
+ }
+ }
+
+ return string;
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ if(!is_init)
+ initClipboard();
+
+ if(is_fail)
+ return;
+
+ if(!is_host)
+ {
+ XSetSelectionOwner(display, selection, window, CurrentTime);
+
+ if(XGetSelectionOwner(display, selection) != window)
+ {
+ std::cerr << "Unable to get ownership of selection." << std::endl;
+ return;
+ }
+
+ pthread_mutex_lock(&mutex);
+ is_host = true;
+ pthread_mutex_unlock(&mutex);
+ }
+
+ pthread_mutex_lock(&mutex);
+ string = text;
+ pthread_mutex_unlock(&mutex);
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Unix/ClipboardImpl.hpp b/src/SFML/Window/Unix/ClipboardImpl.hpp
new file mode 100644
index 0000000..f4aca98
--- /dev/null
+++ b/src/SFML/Window/Unix/ClipboardImpl.hpp
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPLX11_HPP
+#define SFML_CLIPBOARDIMPLX11_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class ClipboardImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String object containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARDIMPLX11_HPP
diff --git a/src/SFML/Window/Unix/CursorImpl.cpp b/src/SFML/Window/Unix/CursorImpl.cpp
new file mode 100644
index 0000000..011a2b1
--- /dev/null
+++ b/src/SFML/Window/Unix/CursorImpl.cpp
@@ -0,0 +1,156 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Unix/CursorImpl.hpp>
+#include <SFML/Window/Unix/Display.hpp>
+#include <X11/cursorfont.h>
+#include <X11/Xutil.h>
+#include <cassert>
+#include <cstdlib>
+#include <vector>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+CursorImpl::CursorImpl() :
+m_display(OpenDisplay()),
+m_cursor(None)
+{
+ // That's it.
+}
+
+
+////////////////////////////////////////////////////////////
+CursorImpl::~CursorImpl()
+{
+ release();
+
+ CloseDisplay(m_display);
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ release();
+
+ // Convert the image into a bitmap (monochrome!).
+ std::size_t bytes = (size.x + 7) / 8 * size.y;
+ std::vector<Uint8> mask(bytes, 0); // Defines which pixel is transparent.
+ std::vector<Uint8> data(bytes, 1); // Defines which pixel is white/black.
+
+ for (std::size_t j = 0; j < size.y; ++j)
+ {
+ for (std::size_t i = 0; i < size.x; ++i)
+ {
+ std::size_t pixelIndex = i + j * size.x;
+ std::size_t byteIndex = pixelIndex / 8;
+ std::size_t bitIndex = i % 8;
+
+ // Turn on pixel that are not transparent
+ Uint8 opacity = pixels[pixelIndex * 4 + 3] > 0 ? 1 : 0;
+ mask[byteIndex] |= opacity << bitIndex;
+
+ // Choose between black/background & white/foreground color for each pixel,
+ // based on the pixel color intensity: on average, if a channel is "active"
+ // at 25%, the bit is white.
+ int intensity = pixels[pixelIndex * 4 + 0] + pixels[pixelIndex * 4 + 1] + pixels[pixelIndex * 4 + 2];
+ Uint8 bit = intensity > 64 ? 1 : 0;
+ data[byteIndex] |= bit << bitIndex;
+ }
+ }
+
+ Pixmap maskPixmap = XCreateBitmapFromData(m_display, XDefaultRootWindow(m_display),
+ (char*)&mask[0], size.x, size.y);
+ Pixmap dataPixmap = XCreateBitmapFromData(m_display, XDefaultRootWindow(m_display),
+ (char*)&data[0], size.x, size.y);
+
+ // Define the foreground color as white and the background as black.
+ XColor fg, bg;
+ fg.red = fg.blue = fg.green = -1;
+ bg.red = bg.blue = bg.green = 0;
+
+ // Create the monochrome cursor.
+ m_cursor = XCreatePixmapCursor(m_display,
+ dataPixmap, maskPixmap,
+ &fg, &bg,
+ hotspot.x, hotspot.y);
+
+ // Free the resources
+ XFreePixmap(m_display, dataPixmap);
+ XFreePixmap(m_display, maskPixmap);
+
+ // We assume everything went fine...
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromSystem(Cursor::Type type)
+{
+ release();
+
+ unsigned int shape;
+ switch (type)
+ {
+ default: return false;
+
+ case Cursor::Arrow: shape = XC_arrow; break;
+ case Cursor::Wait: shape = XC_watch; break;
+ case Cursor::Text: shape = XC_xterm; break;
+ case Cursor::Hand: shape = XC_hand1; break;
+ case Cursor::SizeHorizontal: shape = XC_sb_h_double_arrow; break;
+ case Cursor::SizeVertical: shape = XC_sb_v_double_arrow; break;
+ case Cursor::SizeAll: shape = XC_fleur; break;
+ case Cursor::Cross: shape = XC_crosshair; break;
+ case Cursor::Help: shape = XC_question_arrow; break;
+ case Cursor::NotAllowed: shape = XC_X_cursor; break;
+ }
+
+ m_cursor = XCreateFontCursor(m_display, shape);
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+void CursorImpl::release()
+{
+ if (m_cursor != None)
+ {
+ XFreeCursor(m_display, m_cursor);
+ m_cursor = None;
+ }
+}
+
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/Unix/CursorImpl.hpp b/src/SFML/Window/Unix/CursorImpl.hpp
new file mode 100644
index 0000000..9bd4052
--- /dev/null
+++ b/src/SFML/Window/Unix/CursorImpl.hpp
@@ -0,0 +1,103 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPLUNIX_HPP
+#define SFML_CURSORIMPLUNIX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
+#include <X11/Xlib.h>
+
+namespace sf
+{
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Unix implementation of Cursor
+///
+////////////////////////////////////////////////////////////
+class CursorImpl : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Refer to sf::Cursor::Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// Refer to sf::Cursor::~Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ ~CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// Refer to sf::Cursor::loadFromPixels().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Refer to sf::Cursor::loadFromSystem().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Cursor::Type type);
+
+private:
+
+ friend class WindowImplX11;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Release the cursor, if we have loaded one.
+ ///
+ ////////////////////////////////////////////////////////////
+ void release();
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ ::Display* m_display;
+ ::Cursor m_cursor;
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_CUSROSIMPLUNIX_HPP
diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp
index 60f4c55..351a128 100644
--- a/src/SFML/Window/Unix/Display.cpp
+++ b/src/SFML/Window/Unix/Display.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp
index 0679369..d2bb736 100644
--- a/src/SFML/Window/Unix/Display.hpp
+++ b/src/SFML/Window/Unix/Display.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp
index b16c0e2..cd02236 100644
--- a/src/SFML/Window/Unix/GlxContext.cpp
+++ b/src/SFML/Window/Unix/GlxContext.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -25,8 +25,8 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
+#include <SFML/Window/Unix/WindowImplX11.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Unix/GlxContext.hpp>
-#include <SFML/Window/Unix/WindowImplX11.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
@@ -172,6 +172,9 @@ m_ownsWindow(false)
////////////////////////////////////////////////////////////
GlxContext::~GlxContext()
{
+ // Notify unshared OpenGL resources of context destruction
+ cleanupUnsharedResources();
+
// Destroy the context
if (m_context)
{
diff --git a/src/SFML/Window/Unix/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp
index 3991aba..e974c44 100644
--- a/src/SFML/Window/Unix/GlxContext.hpp
+++ b/src/SFML/Window/Unix/GlxContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/GlxExtensions.cpp b/src/SFML/Window/Unix/GlxExtensions.cpp
index 4d9d978..cfc35b2 100644
--- a/src/SFML/Window/Unix/GlxExtensions.cpp
+++ b/src/SFML/Window/Unix/GlxExtensions.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/GlxExtensions.hpp b/src/SFML/Window/Unix/GlxExtensions.hpp
index 929e38a..abbb132 100644
--- a/src/SFML/Window/Unix/GlxExtensions.hpp
+++ b/src/SFML/Window/Unix/GlxExtensions.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp
index 23c114b..b404dd5 100644
--- a/src/SFML/Window/Unix/InputImpl.cpp
+++ b/src/SFML/Window/Unix/InputImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -54,20 +54,20 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
case Keyboard::RSystem: keysym = XK_Super_R; break;
case Keyboard::Menu: keysym = XK_Menu; break;
case Keyboard::Escape: keysym = XK_Escape; break;
- case Keyboard::SemiColon: keysym = XK_semicolon; break;
+ case Keyboard::Semicolon: keysym = XK_semicolon; break;
case Keyboard::Slash: keysym = XK_slash; break;
case Keyboard::Equal: keysym = XK_equal; break;
- case Keyboard::Dash: keysym = XK_minus; break;
+ case Keyboard::Hyphen: keysym = XK_minus; break;
case Keyboard::LBracket: keysym = XK_bracketleft; break;
case Keyboard::RBracket: keysym = XK_bracketright; break;
case Keyboard::Comma: keysym = XK_comma; break;
case Keyboard::Period: keysym = XK_period; break;
case Keyboard::Quote: keysym = XK_apostrophe; break;
- case Keyboard::BackSlash: keysym = XK_backslash; break;
+ case Keyboard::Backslash: keysym = XK_backslash; break;
case Keyboard::Tilde: keysym = XK_grave; break;
case Keyboard::Space: keysym = XK_space; break;
- case Keyboard::Return: keysym = XK_Return; break;
- case Keyboard::BackSpace: keysym = XK_BackSpace; break;
+ case Keyboard::Enter: keysym = XK_Return; break;
+ case Keyboard::Backspace: keysym = XK_BackSpace; break;
case Keyboard::Tab: keysym = XK_Tab; break;
case Keyboard::PageUp: keysym = XK_Prior; break;
case Keyboard::PageDown: keysym = XK_Next; break;
diff --git a/src/SFML/Window/Unix/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp
index 32ff113..88dcc91 100644
--- a/src/SFML/Window/Unix/InputImpl.hpp
+++ b/src/SFML/Window/Unix/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp
index 2898c6c..56c7234 100644
--- a/src/SFML/Window/Unix/JoystickImpl.cpp
+++ b/src/SFML/Window/Unix/JoystickImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/JoystickImpl.hpp b/src/SFML/Window/Unix/JoystickImpl.hpp
index c62b0df..f81e744 100644
--- a/src/SFML/Window/Unix/JoystickImpl.hpp
+++ b/src/SFML/Window/Unix/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/SensorImpl.cpp b/src/SFML/Window/Unix/SensorImpl.cpp
index 4c00668..3496265 100644
--- a/src/SFML/Window/Unix/SensorImpl.cpp
+++ b/src/SFML/Window/Unix/SensorImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/SensorImpl.hpp b/src/SFML/Window/Unix/SensorImpl.hpp
index a4eedde..2667de3 100644
--- a/src/SFML/Window/Unix/SensorImpl.hpp
+++ b/src/SFML/Window/Unix/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp
index f58d859..288ef3e 100644
--- a/src/SFML/Window/Unix/VideoModeImpl.cpp
+++ b/src/SFML/Window/Unix/VideoModeImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp
index 91086e1..e2c8d29 100644
--- a/src/SFML/Window/Unix/WindowImplX11.cpp
+++ b/src/SFML/Window/Unix/WindowImplX11.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -25,7 +25,6 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
-#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Unix/WindowImplX11.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/InputImpl.hpp>
@@ -67,6 +66,8 @@ namespace
sf::Mutex allWindowsMutex;
sf::String windowManagerName;
+ sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" };
+
static const unsigned long eventMask = FocusChangeMask | ButtonPressMask |
ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask |
@@ -76,6 +77,21 @@ namespace
static const unsigned int maxTrialsCount = 5;
+ // Predicate we use to find key repeat events in processEvent
+ struct KeyRepeatFinder
+ {
+ KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {}
+
+ // Predicate operator that checks event type, keycode and timestamp
+ bool operator()(const XEvent& event)
+ {
+ return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2));
+ }
+
+ unsigned int keycode;
+ Time time;
+ };
+
// Filter the events received by windows (only allow those matching a specific window)
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
{
@@ -261,6 +277,90 @@ namespace
return true;
}
+ // Get the parent window.
+ ::Window getParentWindow(::Display* disp, ::Window win)
+ {
+ ::Window root, parent;
+ ::Window* children = NULL;
+ unsigned int numChildren;
+
+ XQueryTree(disp, win, &root, &parent, &children, &numChildren);
+
+ // Children information is not used, so must be freed.
+ if (children != NULL)
+ XFree(children);
+
+ return parent;
+ }
+
+ // Get the Frame Extents from EWMH WMs that support it.
+ bool getEWMHFrameExtents(::Display* disp, ::Window win,
+ long& xFrameExtent, long& yFrameExtent)
+ {
+ if (!ewmhSupported())
+ return false;
+
+ Atom frameExtents = sf::priv::getAtom("_NET_FRAME_EXTENTS", true);
+
+ if (frameExtents == None)
+ return false;
+
+ bool gotFrameExtents = false;
+ Atom actualType;
+ int actualFormat;
+ unsigned long numItems;
+ unsigned long numBytesLeft;
+ unsigned char* data = NULL;
+
+ int result = XGetWindowProperty(disp,
+ win,
+ frameExtents,
+ 0,
+ 4,
+ False,
+ XA_CARDINAL,
+ &actualType,
+ &actualFormat,
+ &numItems,
+ &numBytesLeft,
+ &data);
+
+ if ((result == Success) && (actualType == XA_CARDINAL) &&
+ (actualFormat == 32) && (numItems == 4) && (numBytesLeft == 0) &&
+ (data != NULL))
+ {
+ gotFrameExtents = true;
+
+ long* extents = (long*) data;
+
+ xFrameExtent = extents[0]; // Left.
+ yFrameExtent = extents[2]; // Top.
+ }
+
+ // Always free data.
+ if (data != NULL)
+ XFree(data);
+
+ return gotFrameExtents;
+ }
+
+ // Check if the current WM is in the list of good WMs that provide
+ // a correct absolute position for the window when queried.
+ bool isWMAbsolutePositionGood()
+ {
+ // This can only work with EWMH, to get the name.
+ if (!ewmhSupported())
+ return false;
+
+ for (size_t i = 0; i < (sizeof(wmAbsPosGood) / sizeof(wmAbsPosGood[0])); i++)
+ {
+ if (wmAbsPosGood[i] == windowManagerName)
+ return true;
+ }
+
+ return false;
+ }
+
sf::Keyboard::Key keysymToSF(KeySym symbol)
{
switch (symbol)
@@ -275,21 +375,21 @@ namespace
case XK_Super_R: return sf::Keyboard::RSystem;
case XK_Menu: return sf::Keyboard::Menu;
case XK_Escape: return sf::Keyboard::Escape;
- case XK_semicolon: return sf::Keyboard::SemiColon;
+ case XK_semicolon: return sf::Keyboard::Semicolon;
case XK_slash: return sf::Keyboard::Slash;
case XK_equal: return sf::Keyboard::Equal;
- case XK_minus: return sf::Keyboard::Dash;
+ case XK_minus: return sf::Keyboard::Hyphen;
case XK_bracketleft: return sf::Keyboard::LBracket;
case XK_bracketright: return sf::Keyboard::RBracket;
case XK_comma: return sf::Keyboard::Comma;
case XK_period: return sf::Keyboard::Period;
case XK_apostrophe: return sf::Keyboard::Quote;
- case XK_backslash: return sf::Keyboard::BackSlash;
+ case XK_backslash: return sf::Keyboard::Backslash;
case XK_grave: return sf::Keyboard::Tilde;
case XK_space: return sf::Keyboard::Space;
- case XK_Return: return sf::Keyboard::Return;
- case XK_KP_Enter: return sf::Keyboard::Return;
- case XK_BackSpace: return sf::Keyboard::BackSpace;
+ case XK_Return: return sf::Keyboard::Enter;
+ case XK_KP_Enter: return sf::Keyboard::Enter;
+ case XK_BackSpace: return sf::Keyboard::Backspace;
case XK_Tab: return sf::Keyboard::Tab;
case XK_Prior: return sf::Keyboard::PageUp;
case XK_Next: return sf::Keyboard::PageDown;
@@ -387,6 +487,7 @@ m_inputContext (NULL),
m_isExternal (true),
m_oldVideoMode (0),
m_hiddenCursor (0),
+m_lastCursor (None),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
@@ -434,6 +535,7 @@ m_inputContext (NULL),
m_isExternal (false),
m_oldVideoMode (0),
m_hiddenCursor (0),
+m_lastCursor (None),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
@@ -665,8 +767,16 @@ WindowHandle WindowImplX11::getSystemHandle() const
void WindowImplX11::processEvents()
{
XEvent event;
+
+ // Pick out the events that are interesting for this window
while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
+ m_events.push_back(event);
+
+ // Handle the events for this window that we just picked out
+ while (!m_events.empty())
{
+ event = m_events.front();
+ m_events.pop_front();
processEvent(event);
}
}
@@ -675,14 +785,67 @@ void WindowImplX11::processEvents()
////////////////////////////////////////////////////////////
Vector2i WindowImplX11::getPosition() const
{
- ::Window root, child;
- int localX, localY, x, y;
- unsigned int width, height, border, depth;
+ // Get absolute position of our window relative to root window. This
+ // takes into account all information that X11 has, including X11
+ // border widths and any decorations. It corresponds to where the
+ // window actually is, but not necessarily to where we told it to
+ // go using setPosition() and XMoveWindow(). To have the two match
+ // as expected, we may have to subtract decorations and borders.
+ ::Window child;
+ int xAbsRelToRoot, yAbsRelToRoot;
+
+ XTranslateCoordinates(m_display, m_window, DefaultRootWindow(m_display),
+ 0, 0, &xAbsRelToRoot, &yAbsRelToRoot, &child);
+
+ // CASE 1: some rare WMs actually put the window exactly where we tell
+ // it to, even with decorations and such, which get shifted back.
+ // In these rare cases, we can use the absolute value directly.
+ if (isWMAbsolutePositionGood())
+ return Vector2i(xAbsRelToRoot, yAbsRelToRoot);
+
+ // CASE 2: most modern WMs support EWMH and can define _NET_FRAME_EXTENTS
+ // with the exact frame size to subtract, so if present, we prefer it and
+ // query it first. According to spec, this already includes any borders.
+ long xFrameExtent, yFrameExtent;
+
+ if (getEWMHFrameExtents(m_display, m_window, xFrameExtent, yFrameExtent))
+ {
+ // Get final X/Y coordinates: subtract EWMH frame extents from
+ // absolute window position.
+ return Vector2i((xAbsRelToRoot - xFrameExtent), (yAbsRelToRoot - yFrameExtent));
+ }
+
+ // CASE 3: EWMH frame extents were not available, use geometry.
+ // We climb back up to the window before the root and use its
+ // geometry information to extract X/Y position. This because
+ // re-parenting WMs may re-parent the window multiple times, so
+ // we'd have to climb up to the furthest ancestor and sum the
+ // relative differences and borders anyway; and doing that to
+ // subtract those values from the absolute coordinates of the
+ // window is equivalent to going up the tree and asking the
+ // furthest ancestor what it's relative distance to the root is.
+ // So we use that approach because it's simpler.
+ // This approach assumes that any window between the root and
+ // our window is part of decorations/borders in some way. This
+ // seems to hold true for most reasonable WM implementations.
+ ::Window ancestor = m_window;
+ ::Window root = DefaultRootWindow(m_display);
+
+ while (getParentWindow(m_display, ancestor) != root)
+ {
+ // Next window up (parent window).
+ ancestor = getParentWindow(m_display, ancestor);
+ }
- XGetGeometry(m_display, m_window, &root, &localX, &localY, &width, &height, &border, &depth);
- XTranslateCoordinates(m_display, m_window, root, localX, localY, &x, &y, &child);
+ // Get final X/Y coordinates: take the relative position to
+ // the root of the furthest ancestor window.
+ int xRelToRoot, yRelToRoot;
+ unsigned int width, height, borderWidth, depth;
- return Vector2i(x, y);
+ XGetGeometry(m_display, ancestor, &root, &xRelToRoot, &yRelToRoot,
+ &width, &height, &borderWidth, &depth);
+
+ return Vector2i(xRelToRoot, yRelToRoot);
}
@@ -871,6 +1034,9 @@ void WindowImplX11::setVisible(bool visible)
{
XMapWindow(m_display, m_window);
+ if(m_fullscreen)
+ switchToFullscreen();
+
XFlush(m_display);
// Before continuing, make sure the WM has
@@ -895,12 +1061,20 @@ void WindowImplX11::setVisible(bool visible)
////////////////////////////////////////////////////////////
void WindowImplX11::setMouseCursorVisible(bool visible)
{
- XDefineCursor(m_display, m_window, visible ? None : m_hiddenCursor);
+ XDefineCursor(m_display, m_window, visible ? m_lastCursor : m_hiddenCursor);
XFlush(m_display);
}
////////////////////////////////////////////////////////////
+void WindowImplX11::setMouseCursor(const CursorImpl& cursor)
+{
+ m_lastCursor = cursor.m_cursor;
+ XDefineCursor(m_display, m_window, m_lastCursor);
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
{
// This has no effect in fullscreen mode
@@ -1385,29 +1559,23 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false
// Detect repeated key events
- // (code shamelessly taken from SDL)
if (windowEvent.type == KeyRelease)
{
- // Check if there's a matching KeyPress event in the queue
- XEvent nextEvent;
- if (XPending(m_display))
+ // Find the next KeyPress event with matching keycode and time
+ std::deque<XEvent>::iterator iter = std::find_if(
+ m_events.begin(),
+ m_events.end(),
+ KeyRepeatFinder(windowEvent.xkey.keycode, windowEvent.xkey.time)
+ );
+
+ if (iter != m_events.end())
{
- // Grab it but don't remove it from the queue, it still needs to be processed :)
- XPeekEvent(m_display, &nextEvent);
- if (nextEvent.type == KeyPress)
- {
- // Check if it is a duplicated event (same timestamp as the KeyRelease event)
- if ((nextEvent.xkey.keycode == windowEvent.xkey.keycode) &&
- (nextEvent.xkey.time - windowEvent.xkey.time < 2))
- {
- // If we don't want repeated events, remove the next KeyPress from the queue
- if (!m_keyRepeat)
- XNextEvent(m_display, &nextEvent);
+ // If we don't want repeated events, remove the next KeyPress from the queue
+ if (!m_keyRepeat)
+ m_events.erase(iter);
- // This KeyRelease is a repeated event and we don't want it
- return false;
- }
- }
+ // This KeyRelease is a repeated event and we don't want it
+ return false;
}
}
diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp
index 973a57d..0ff694b 100644
--- a/src/SFML/Window/Unix/WindowImplX11.hpp
+++ b/src/SFML/Window/Unix/WindowImplX11.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,7 @@
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/String.hpp>
+#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
#include <X11/Xlib.h>
#include <deque>
@@ -155,6 +156,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
@@ -258,23 +267,25 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- ::Window m_window; ///< X identifier defining our window
- ::Display* m_display; ///< Pointer to the display
- int m_screen; ///< Screen identifier
- XIM m_inputMethod; ///< Input method linked to the X display
- XIC m_inputContext; ///< Input context used to get unicode input in our window
- bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
- int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
- Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
- bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
- Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
- bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
- bool m_fullscreen; ///< Is the window in fullscreen?
- bool m_cursorGrabbed; ///< Is the mouse cursor trapped?
- bool m_windowMapped; ///< Has the window been mapped by the window manager?
- Pixmap m_iconPixmap; ///< The current icon pixmap if in use
- Pixmap m_iconMaskPixmap; ///< The current icon mask pixmap if in use
- ::Time m_lastInputTime; ///< Last time we received user input
+ ::Window m_window; ///< X identifier defining our window
+ ::Display* m_display; ///< Pointer to the display
+ int m_screen; ///< Screen identifier
+ XIM m_inputMethod; ///< Input method linked to the X display
+ XIC m_inputContext; ///< Input context used to get unicode input in our window
+ std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
+ bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
+ int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
+ ::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
+ ::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
+ bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
+ Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
+ bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
+ bool m_fullscreen; ///< Is the window in fullscreen?
+ bool m_cursorGrabbed; ///< Is the mouse cursor trapped?
+ bool m_windowMapped; ///< Has the window been mapped by the window manager?
+ Pixmap m_iconPixmap; ///< The current icon pixmap if in use
+ Pixmap m_iconMaskPixmap; ///< The current icon mask pixmap if in use
+ ::Time m_lastInputTime; ///< Last time we received user input
};
} // namespace priv
diff --git a/src/SFML/Window/VideoMode.cpp b/src/SFML/Window/VideoMode.cpp
index 0110389..12c3801 100644
--- a/src/SFML/Window/VideoMode.cpp
+++ b/src/SFML/Window/VideoMode.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/VideoModeImpl.hpp b/src/SFML/Window/VideoModeImpl.hpp
index 525e998..7371472 100644
--- a/src/SFML/Window/VideoModeImpl.hpp
+++ b/src/SFML/Window/VideoModeImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/ClipboardImpl.cpp b/src/SFML/Window/Win32/ClipboardImpl.cpp
new file mode 100644
index 0000000..13fd06f
--- /dev/null
+++ b/src/SFML/Window/Win32/ClipboardImpl.cpp
@@ -0,0 +1,103 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Win32/ClipboardImpl.hpp>
+#include <SFML/System/String.hpp>
+#include <iostream>
+#include <windows.h>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getString()
+{
+ String text;
+
+ if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
+ {
+ std::cerr << "Failed to get the clipboard data in Unicode format." << std::endl;
+ return text;
+ }
+
+ if (!OpenClipboard(NULL))
+ {
+ std::cerr << "Failed to open the Win32 clipboard." << std::endl;
+ return text;
+ }
+
+ HANDLE clipboard_handle = GetClipboardData(CF_UNICODETEXT);
+
+ if (!clipboard_handle)
+ {
+ std::cerr << "Failed to get Win32 handle for clipboard content." << std::endl;
+ CloseClipboard();
+ return text;
+ }
+
+ text = String(static_cast<wchar_t*>(GlobalLock(clipboard_handle)));
+ GlobalUnlock(clipboard_handle);
+
+ CloseClipboard();
+ return text;
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ if (!OpenClipboard(NULL))
+ {
+ std::cerr << "Failed to open the Win32 clipboard." << std::endl;
+ return;
+ }
+
+ if (!EmptyClipboard())
+ {
+ std::cerr << "Failed to empty the Win32 clipboard." << std::endl;
+ return;
+ }
+
+ // Create a Win32-compatible string
+ size_t string_size = (text.getSize() + 1) * sizeof(WCHAR);
+ HANDLE string_handle = GlobalAlloc(GMEM_MOVEABLE, string_size);
+
+ if (string_handle)
+ {
+ memcpy(GlobalLock(string_handle), text.toWideString().data(), string_size);
+ GlobalUnlock(string_handle);
+ SetClipboardData(CF_UNICODETEXT, string_handle);
+ }
+
+ CloseClipboard();
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Win32/ClipboardImpl.hpp b/src/SFML/Window/Win32/ClipboardImpl.hpp
new file mode 100644
index 0000000..c42ec5e
--- /dev/null
+++ b/src/SFML/Window/Win32/ClipboardImpl.hpp
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPLWIN32_HPP
+#define SFML_CLIPBOARDIMPLWIN32_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class ClipboardImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String object containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARDIMPLWIN32_HPP
diff --git a/src/SFML/Window/Win32/CursorImpl.cpp b/src/SFML/Window/Win32/CursorImpl.cpp
new file mode 100755
index 0000000..28f4274
--- /dev/null
+++ b/src/SFML/Window/Win32/CursorImpl.cpp
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Win32/CursorImpl.hpp>
+#include <SFML/System/Err.hpp>
+#include <cstring>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+CursorImpl::CursorImpl() :
+m_cursor(NULL)
+{
+ // That's it.
+}
+
+
+////////////////////////////////////////////////////////////
+CursorImpl::~CursorImpl()
+{
+ release();
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ release();
+
+ // Create the bitmap that will hold our color data
+ BITMAPV5HEADER bitmapHeader;
+ std::memset(&bitmapHeader, 0, sizeof(BITMAPV5HEADER));
+
+ bitmapHeader.bV5Size = sizeof(BITMAPV5HEADER);
+ bitmapHeader.bV5Width = size.x;
+ bitmapHeader.bV5Height = -static_cast<int>(size.y); // Negative indicates origin is in upper-left corner
+ bitmapHeader.bV5Planes = 1;
+ bitmapHeader.bV5BitCount = 32;
+ bitmapHeader.bV5Compression = BI_BITFIELDS;
+ bitmapHeader.bV5RedMask = 0x00ff0000;
+ bitmapHeader.bV5GreenMask = 0x0000ff00;
+ bitmapHeader.bV5BlueMask = 0x000000ff;
+ bitmapHeader.bV5AlphaMask = 0xff000000;
+
+ Uint8* bitmapData = NULL;
+
+ HDC screenDC = GetDC(NULL);
+ HBITMAP color = CreateDIBSection(
+ screenDC,
+ reinterpret_cast<const BITMAPINFO*>(&bitmapHeader),
+ DIB_RGB_COLORS,
+ reinterpret_cast<void**>(&bitmapData),
+ NULL,
+ 0
+ );
+ ReleaseDC(NULL, screenDC);
+
+ if (!color)
+ {
+ err() << "Failed to create cursor color bitmap" << std::endl;
+ return false;
+ }
+
+ // Fill our bitmap with the cursor color data
+ std::memcpy(bitmapData, pixels, size.x * size.y * 4);
+
+ // Create a dummy mask bitmap (it won't be used)
+ HBITMAP mask = CreateBitmap(size.x, size.y, 1, 1, NULL);
+
+ if (!mask)
+ {
+ DeleteObject(color);
+ err() << "Failed to create cursor mask bitmap" << std::endl;
+ return false;
+ }
+
+ // Create the structure that describes our cursor
+ ICONINFO cursorInfo;
+ std::memset(&cursorInfo, 0, sizeof(ICONINFO));
+
+ cursorInfo.fIcon = FALSE; // This is a cursor and not an icon
+ cursorInfo.xHotspot = hotspot.x;
+ cursorInfo.yHotspot = hotspot.y;
+ cursorInfo.hbmColor = color;
+ cursorInfo.hbmMask = mask;
+
+ // Create the cursor
+ m_cursor = reinterpret_cast<HCURSOR>(CreateIconIndirect(&cursorInfo));
+
+ // The data has been copied into the cursor, so get rid of these
+ DeleteObject(color);
+ DeleteObject(mask);
+
+ if (m_cursor)
+ {
+ return true;
+ }
+ else
+ {
+ err() << "Failed to create cursor from bitmaps" << std::endl;
+ return false;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromSystem(Cursor::Type type)
+{
+ release();
+
+ LPCTSTR shape;
+ switch (type)
+ {
+ case Cursor::Arrow: shape = IDC_ARROW; break;
+ case Cursor::ArrowWait: shape = IDC_APPSTARTING; break;
+ case Cursor::Wait: shape = IDC_WAIT; break;
+ case Cursor::Text: shape = IDC_IBEAM; break;
+ case Cursor::Hand: shape = IDC_HAND; break;
+ case Cursor::SizeHorizontal: shape = IDC_SIZEWE; break;
+ case Cursor::SizeVertical: shape = IDC_SIZENS; break;
+ case Cursor::SizeTopLeftBottomRight: shape = IDC_SIZENWSE; break;
+ case Cursor::SizeBottomLeftTopRight: shape = IDC_SIZENESW; break;
+ case Cursor::SizeAll: shape = IDC_SIZEALL; break;
+ case Cursor::Cross: shape = IDC_CROSS; break;
+ case Cursor::Help: shape = IDC_HELP; break;
+ case Cursor::NotAllowed: shape = IDC_NO; break;
+ }
+
+ // Create a copy of the shared system cursor that we can destroy later
+ m_cursor = CopyCursor(LoadCursor(NULL, shape));
+
+ if (m_cursor)
+ {
+ return true;
+ }
+ else
+ {
+ err() << "Could not create copy of a system cursor" << std::endl;
+ return false;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void CursorImpl::release()
+{
+ if (m_cursor) {
+ DestroyCursor(m_cursor);
+ m_cursor = NULL;
+ }
+}
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/Win32/CursorImpl.hpp b/src/SFML/Window/Win32/CursorImpl.hpp
new file mode 100755
index 0000000..602f223
--- /dev/null
+++ b/src/SFML/Window/Win32/CursorImpl.hpp
@@ -0,0 +1,103 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPLWIN32_HPP
+#define SFML_CURSORIMPLWIN32_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+
+#include <windows.h>
+
+namespace sf
+{
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Win32 implementation of Cursor
+///
+////////////////////////////////////////////////////////////
+class CursorImpl : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Refer to sf::Cursor::Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// Refer to sf::Cursor::~Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ ~CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// Refer to sf::Cursor::loadFromPixels().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Refer to sf::Cursor::loadFromSystem().
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Cursor::Type type);
+
+private:
+
+ friend class WindowImplWin32;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Release the cursor, if we have loaded one.
+ ///
+ ////////////////////////////////////////////////////////////
+ void release();
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ HCURSOR m_cursor;
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_CUSROSIMPLWIN32_HPP
+
diff --git a/src/SFML/Window/Win32/InputImpl.cpp b/src/SFML/Window/Win32/InputImpl.cpp
index d5d3e56..0482740 100644
--- a/src/SFML/Window/Win32/InputImpl.cpp
+++ b/src/SFML/Window/Win32/InputImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -97,18 +97,18 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
case Keyboard::Menu: vkey = VK_APPS; break;
case Keyboard::LBracket: vkey = VK_OEM_4; break;
case Keyboard::RBracket: vkey = VK_OEM_6; break;
- case Keyboard::SemiColon: vkey = VK_OEM_1; break;
+ case Keyboard::Semicolon: vkey = VK_OEM_1; break;
case Keyboard::Comma: vkey = VK_OEM_COMMA; break;
case Keyboard::Period: vkey = VK_OEM_PERIOD; break;
case Keyboard::Quote: vkey = VK_OEM_7; break;
case Keyboard::Slash: vkey = VK_OEM_2; break;
- case Keyboard::BackSlash: vkey = VK_OEM_5; break;
+ case Keyboard::Backslash: vkey = VK_OEM_5; break;
case Keyboard::Tilde: vkey = VK_OEM_3; break;
case Keyboard::Equal: vkey = VK_OEM_PLUS; break;
- case Keyboard::Dash: vkey = VK_OEM_MINUS; break;
+ case Keyboard::Hyphen: vkey = VK_OEM_MINUS; break;
case Keyboard::Space: vkey = VK_SPACE; break;
- case Keyboard::Return: vkey = VK_RETURN; break;
- case Keyboard::BackSpace: vkey = VK_BACK; break;
+ case Keyboard::Enter: vkey = VK_RETURN; break;
+ case Keyboard::Backspace: vkey = VK_BACK; break;
case Keyboard::Tab: vkey = VK_TAB; break;
case Keyboard::PageUp: vkey = VK_PRIOR; break;
case Keyboard::PageDown: vkey = VK_NEXT; break;
diff --git a/src/SFML/Window/Win32/InputImpl.hpp b/src/SFML/Window/Win32/InputImpl.hpp
index 708472c..17ac482 100644
--- a/src/SFML/Window/Win32/InputImpl.hpp
+++ b/src/SFML/Window/Win32/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/JoystickImpl.cpp b/src/SFML/Window/Win32/JoystickImpl.cpp
index 7ea5df6..1b98d9d 100644
--- a/src/SFML/Window/Win32/JoystickImpl.cpp
+++ b/src/SFML/Window/Win32/JoystickImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -33,9 +33,59 @@
#include <regstr.h>
#include <algorithm>
#include <cmath>
+#include <cstring>
#include <sstream>
#include <string>
+#include <vector>
+
+
+////////////////////////////////////////////////////////////
+// DirectInput
+////////////////////////////////////////////////////////////
+
+
+#ifndef DIDFT_OPTIONAL
+#define DIDFT_OPTIONAL 0x80000000
+#endif
+
+
+namespace
+{
+ namespace guids
+ {
+ const GUID IID_IDirectInput8W = {0xbf798031, 0x483a, 0x4da2, {0xaa, 0x99, 0x5d, 0x64, 0xed, 0x36, 0x97, 0x00}};
+
+ const GUID GUID_XAxis = {0xa36d02e0, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ const GUID GUID_YAxis = {0xa36d02e1, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ const GUID GUID_ZAxis = {0xa36d02e2, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ const GUID GUID_RzAxis = {0xa36d02e3, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ const GUID GUID_Slider = {0xa36d02e4, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+
+ const GUID GUID_POV = {0xa36d02f2, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+
+ const GUID GUID_RxAxis = {0xa36d02f4, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ const GUID GUID_RyAxis = {0xa36d02f5, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+ }
+
+ HMODULE dinput8dll = NULL;
+ IDirectInput8W* directInput = NULL;
+
+ struct JoystickRecord
+ {
+ GUID guid;
+ unsigned int index;
+ bool plugged;
+ };
+
+ typedef std::vector<JoystickRecord> JoystickList;
+ JoystickList joystickList;
+}
+
+
+////////////////////////////////////////////////////////////
+// Legacy joystick API
+////////////////////////////////////////////////////////////
namespace
{
struct ConnectionCache
@@ -44,10 +94,13 @@ namespace
bool connected;
sf::Clock timer;
};
-
const sf::Time connectionRefreshDelay = sf::milliseconds(500);
+
ConnectionCache connectionCache[sf::Joystick::Count];
+ // If true, will only update when WM_DEVICECHANGE message is received
+ bool lazyUpdates = false;
+
// Get a system error string from an error code
std::string getErrorString(DWORD error)
{
@@ -149,58 +202,74 @@ namespace priv
////////////////////////////////////////////////////////////
void JoystickImpl::initialize()
{
- // Perform the initial scan and populate the connection cache
- for (unsigned int i = 0; i < Joystick::Count; ++i)
- {
- ConnectionCache& cache = connectionCache[i];
+ // Try to initialize DirectInput
+ initializeDInput();
- // Check if the joystick is connected
- JOYINFOEX joyInfo;
- joyInfo.dwSize = sizeof(joyInfo);
- joyInfo.dwFlags = 0;
- cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR;
+ if (!directInput)
+ err() << "DirectInput not available, falling back to Windows joystick API" << std::endl;
- // start the timeout
- cache.timer.restart();
- }
+ // Perform the initial scan and populate the connection cache
+ updateConnections();
}
////////////////////////////////////////////////////////////
void JoystickImpl::cleanup()
{
- // Nothing to do
+ // Clean up DirectInput
+ cleanupDInput();
}
////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index)
{
- // We check the connection state of joysticks only every N milliseconds,
- // because of a strange (buggy?) behavior of joyGetPosEx when joysticks
- // are just plugged/unplugged -- it takes really long and kills the app performances
+ if (directInput)
+ return isConnectedDInput(index);
+
ConnectionCache& cache = connectionCache[index];
- if (cache.timer.getElapsedTime() > connectionRefreshDelay)
+ if (!lazyUpdates && cache.timer.getElapsedTime() > connectionRefreshDelay)
{
- cache.timer.restart();
-
JOYINFOEX joyInfo;
joyInfo.dwSize = sizeof(joyInfo);
joyInfo.dwFlags = 0;
-
cache.connected = joyGetPosEx(JOYSTICKID1 + index, &joyInfo) == JOYERR_NOERROR;
- return cache.connected;
+
+ cache.timer.restart();
}
- else
+ return cache.connected;
+}
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::setLazyUpdates(bool status)
+{
+ lazyUpdates = status;
+}
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::updateConnections()
+{
+ if (directInput)
+ return updateConnectionsDInput();
+
+ for (unsigned int i = 0; i < Joystick::Count; ++i)
{
- return cache.connected;
+ JOYINFOEX joyInfo;
+ joyInfo.dwSize = sizeof(joyInfo);
+ joyInfo.dwFlags = 0;
+ ConnectionCache& cache = connectionCache[i];
+ cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR;
+
+ cache.timer.restart();
}
}
-
////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index)
{
+ if (directInput)
+ return openDInput(index);
+
// No explicit "open" action is required
m_index = JOYSTICKID1 + index;
@@ -221,12 +290,16 @@ bool JoystickImpl::open(unsigned int index)
////////////////////////////////////////////////////////////
void JoystickImpl::close()
{
- // Nothing to do
+ if (directInput)
+ closeDInput();
}
////////////////////////////////////////////////////////////
JoystickCaps JoystickImpl::getCapabilities() const
{
+ if (directInput)
+ return getCapabilitiesDInput();
+
JoystickCaps caps;
caps.buttonCount = m_caps.wNumButtons;
@@ -256,6 +329,9 @@ Joystick::Identification JoystickImpl::getIdentification() const
////////////////////////////////////////////////////////////
JoystickState JoystickImpl::update()
{
+ if (directInput)
+ return updateDInput();
+
JoystickState state;
// Get the current joystick state
@@ -297,6 +373,548 @@ JoystickState JoystickImpl::update()
return state;
}
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::initializeDInput()
+{
+ // Try to load dinput8.dll
+ dinput8dll = LoadLibraryA("dinput8.dll");
+
+ if (dinput8dll)
+ {
+ // Try to get the address of the DirectInput8Create entry point
+ typedef HRESULT(WINAPI *DirectInput8CreateFunc)(HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN);
+ DirectInput8CreateFunc directInput8Create = reinterpret_cast<DirectInput8CreateFunc>(GetProcAddress(dinput8dll, "DirectInput8Create"));
+
+ if (directInput8Create)
+ {
+ // Try to acquire a DirectInput 8.x interface
+ HRESULT result = directInput8Create(GetModuleHandleW(NULL), 0x0800, guids::IID_IDirectInput8W, reinterpret_cast<void**>(&directInput), NULL);
+
+ if (result)
+ {
+ // De-initialize everything
+ directInput = NULL;
+ FreeLibrary(dinput8dll);
+ dinput8dll = NULL;
+
+ err() << "Failed to initialize DirectInput: " << result << std::endl;
+ }
+ }
+ else
+ {
+ // Unload dinput8.dll
+ FreeLibrary(dinput8dll);
+ dinput8dll = NULL;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::cleanupDInput()
+{
+ // Release the DirectInput interface
+ if (directInput)
+ {
+ directInput->Release();
+ directInput = NULL;
+ }
+
+ // Unload dinput8.dll
+ if (dinput8dll)
+ FreeLibrary(dinput8dll);
+}
+
+
+////////////////////////////////////////////////////////////
+bool JoystickImpl::isConnectedDInput(unsigned int index)
+{
+ // Check if a joystick with the given index is in the connected list
+ for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
+ {
+ if (i->index == index)
+ return true;
+ }
+
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::updateConnectionsDInput()
+{
+ // Clear plugged flags so we can determine which devices were added/removed
+ for (std::size_t i = 0; i < joystickList.size(); ++i)
+ joystickList[i].plugged = false;
+
+ // Enumerate devices
+ HRESULT result = directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, &JoystickImpl::deviceEnumerationCallback, NULL, DIEDFL_ATTACHEDONLY);
+
+ // Remove devices that were not connected during the enumeration
+ for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end();)
+ {
+ if (!i->plugged)
+ i = joystickList.erase(i);
+ else
+ ++i;
+ }
+
+ if (result)
+ {
+ err() << "Failed to enumerate DirectInput devices: " << result << std::endl;
+
+ return;
+ }
+
+ // Assign unused joystick indices to devices that were newly connected
+ for (unsigned int i = 0; i < Joystick::Count; ++i)
+ {
+ for (std::vector<JoystickRecord>::iterator j = joystickList.begin(); j != joystickList.end(); ++j)
+ {
+ if (j->index == i)
+ break;
+
+ if (j->index == Joystick::Count)
+ {
+ j->index = i;
+ break;
+ }
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool JoystickImpl::openDInput(unsigned int index)
+{
+ // Initialize DirectInput members
+ m_device = NULL;
+
+ for (int i = 0; i < Joystick::AxisCount; ++i)
+ m_axes[i] = -1;
+
+ for (int i = 0; i < Joystick::ButtonCount; ++i)
+ m_buttons[i] = -1;
+
+ std::memset(&m_deviceCaps, 0, sizeof(DIDEVCAPS));
+ m_deviceCaps.dwSize = sizeof(DIDEVCAPS);
+
+ // Search for a joystick with the given index in the connected list
+ for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
+ {
+ if (i->index == index)
+ {
+ // Create device
+ HRESULT result = directInput->CreateDevice(i->guid, &m_device, NULL);
+
+ if (result)
+ {
+ err() << "Failed to create DirectInput device: " << result << std::endl;
+
+ return false;
+ }
+
+ static bool formatInitialized = false;
+ static DIDATAFORMAT format;
+
+ if (!formatInitialized)
+ {
+ const DWORD axisType = DIDFT_AXIS | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
+ const DWORD povType = DIDFT_POV | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
+ const DWORD buttonType = DIDFT_BUTTON | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
+
+ static DIOBJECTDATAFORMAT data[8 + 4 + sf::Joystick::ButtonCount];
+
+ data[0].pguid = &guids::GUID_XAxis;
+ data[0].dwOfs = DIJOFS_X;
+
+ data[1].pguid = &guids::GUID_YAxis;
+ data[1].dwOfs = DIJOFS_Y;
+
+ data[2].pguid = &guids::GUID_ZAxis;
+ data[2].dwOfs = DIJOFS_Z;
+
+ data[3].pguid = &guids::GUID_RxAxis;
+ data[3].dwOfs = DIJOFS_RX;
+
+ data[4].pguid = &guids::GUID_RyAxis;
+ data[4].dwOfs = DIJOFS_RY;
+
+ data[5].pguid = &guids::GUID_RzAxis;
+ data[5].dwOfs = DIJOFS_RZ;
+
+ data[6].pguid = &guids::GUID_Slider;
+ data[6].dwOfs = DIJOFS_SLIDER(0);
+
+ data[7].pguid = &guids::GUID_Slider;
+ data[7].dwOfs = DIJOFS_SLIDER(1);
+
+ for (int i = 0; i < 8; ++i)
+ {
+ data[i].dwType = axisType;
+ data[i].dwFlags = DIDOI_ASPECTPOSITION;
+ }
+
+ for (int i = 0; i < 4; ++i)
+ {
+ data[8 + i].pguid = &guids::GUID_POV;
+ data[8 + i].dwOfs = static_cast<DWORD>(DIJOFS_POV(i));
+ data[8 + i].dwType = povType;
+ data[8 + i].dwFlags = 0;
+ }
+
+ for (int i = 0; i < sf::Joystick::ButtonCount; ++i)
+ {
+ data[8 + 4 + i].pguid = NULL;
+ data[8 + 4 + i].dwOfs = static_cast<DWORD>(DIJOFS_BUTTON(i));
+ data[8 + 4 + i].dwType = buttonType;
+ data[8 + 4 + i].dwFlags = 0;
+ }
+
+ format.dwSize = sizeof(DIDATAFORMAT);
+ format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
+ format.dwFlags = DIDFT_ABSAXIS;
+ format.dwDataSize = sizeof(DIJOYSTATE);
+ format.dwNumObjs = 8 + 4 + sf::Joystick::ButtonCount;
+ format.rgodf = data;
+
+ formatInitialized = true;
+ }
+
+ // Set device data format
+ result = m_device->SetDataFormat(&format);
+
+ if (result)
+ {
+ err() << "Failed to set DirectInput device data format: " << result << std::endl;
+
+ m_device->Release();
+ m_device = NULL;
+
+ return false;
+ }
+
+ // Get device capabilities
+ result = m_device->GetCapabilities(&m_deviceCaps);
+
+ if (result)
+ {
+ err() << "Failed to get DirectInput device capabilities: " << result << std::endl;
+
+ m_device->Release();
+ m_device = NULL;
+
+ return false;
+ }
+
+ // Set axis mode to absolute
+ DIPROPDWORD property;
+ std::memset(&property, 0, sizeof(property));
+ property.diph.dwSize = sizeof(property);
+ property.diph.dwHeaderSize = sizeof(property.diph);
+ property.diph.dwHow = DIPH_DEVICE;
+ property.dwData = DIPROPAXISMODE_ABS;
+
+ result = m_device->SetProperty(DIPROP_AXISMODE, &property.diph);
+
+ if (result)
+ {
+ err() << "Failed to set DirectInput device axis mode: " << result << std::endl;
+
+ m_device->Release();
+ m_device = NULL;
+
+ return false;
+ }
+
+ // Enumerate device objects (axes/povs/buttons)
+ result = m_device->EnumObjects(&JoystickImpl::deviceObjectEnumerationCallback, this, DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
+
+ if (result)
+ {
+ err() << "Failed to enumerate DirectInput device objects: " << result << std::endl;
+
+ m_device->Release();
+ m_device = NULL;
+
+ return false;
+ }
+
+ // Get friendly product name of the device
+ DIPROPSTRING stringProperty;
+ std::memset(&stringProperty, 0, sizeof(stringProperty));
+ stringProperty.diph.dwSize = sizeof(stringProperty);
+ stringProperty.diph.dwHeaderSize = sizeof(stringProperty.diph);
+ stringProperty.diph.dwHow = DIPH_DEVICE;
+ stringProperty.diph.dwObj = 0;
+
+ if (!m_device->GetProperty(DIPROP_PRODUCTNAME, &stringProperty.diph))
+ {
+ m_identification.name = stringProperty.wsz;
+ }
+
+ // Get vendor and produce id of the device
+ std::memset(&property, 0, sizeof(property));
+ property.diph.dwSize = sizeof(property);
+ property.diph.dwHeaderSize = sizeof(property.diph);
+ property.diph.dwHow = DIPH_DEVICE;
+
+ if (!m_device->GetProperty(DIPROP_VIDPID, &property.diph))
+ {
+ m_identification.productId = HIWORD(property.dwData);
+ m_identification.vendorId = LOWORD(property.dwData);
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+void JoystickImpl::closeDInput()
+{
+ if (m_device)
+ {
+ // Release the device
+ m_device->Release();
+ m_device = NULL;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+JoystickCaps JoystickImpl::getCapabilitiesDInput() const
+{
+ JoystickCaps caps;
+
+ // Count how many buttons have valid offsets
+ caps.buttonCount = 0;
+
+ for (int i = 0; i < Joystick::ButtonCount; ++i)
+ {
+ if (m_buttons[i] != -1)
+ ++caps.buttonCount;
+ }
+
+ // Check which axes have valid offsets
+ for (int i = 0; i < Joystick::AxisCount; ++i)
+ caps.axes[i] = (m_axes[i] != -1);
+
+ return caps;
+}
+
+
+////////////////////////////////////////////////////////////
+JoystickState JoystickImpl::updateDInput()
+{
+ JoystickState state;
+
+ if (m_device)
+ {
+ // Poll the device
+ m_device->Poll();
+
+ DIJOYSTATE joystate;
+
+ // Try to get the device state
+ HRESULT result = m_device->GetDeviceState(sizeof(joystate), &joystate);
+
+ // If we have not acquired or have lost the device, attempt to (re-)acquire it and get the device state again
+ if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
+ {
+ m_device->Acquire();
+ m_device->Poll();
+ result = m_device->GetDeviceState(sizeof(joystate), &joystate);
+ }
+
+ // If we still can't get the device state, assume it has been disconnected
+ if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
+ {
+ m_device->Release();
+ m_device = NULL;
+
+ return state;
+ }
+
+ if (result)
+ {
+ err() << "Failed to get DirectInput device state: " << result << std::endl;
+
+ return state;
+ }
+
+ // Get the current state of each axis
+ for (int i = 0; i < Joystick::AxisCount; ++i)
+ {
+ if (m_axes[i] != -1)
+ {
+ if (i == Joystick::PovX)
+ {
+ unsigned short value = LOWORD(*reinterpret_cast<const DWORD*>(reinterpret_cast<const char*>(&joystate) + m_axes[i]));
+
+ if (value != 0xFFFF)
+ {
+ float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
+
+ state.axes[i] = std::sin(angle) * 100.f;
+ }
+ else
+ {
+ state.axes[i] = 0;
+ }
+ }
+ else if (i == Joystick::PovY)
+ {
+ unsigned short value = LOWORD(*reinterpret_cast<const DWORD*>(reinterpret_cast<const char*>(&joystate) + m_axes[i]));
+
+ if (value != 0xFFFF)
+ {
+ float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
+
+ state.axes[i] = std::cos(angle) * 100.f;
+ }
+ else
+ {
+ state.axes[i] = 0.f;
+ }
+ }
+ else
+ {
+ state.axes[i] = (static_cast<float>(*reinterpret_cast<const LONG*>(reinterpret_cast<const char*>(&joystate) + m_axes[i])) + 0.5f) * 100.f / 32767.5f;
+ }
+ }
+ else
+ {
+ state.axes[i] = 0.f;
+ }
+ }
+
+ // Get the current state of each button
+ for (int i = 0; i < Joystick::ButtonCount; ++i)
+ {
+ if (m_buttons[i] != -1)
+ {
+ BYTE value = *reinterpret_cast<const BYTE*>(reinterpret_cast<const char*>(&joystate) + m_buttons[i]);
+
+ state.buttons[i] = ((value & 0x80) != 0);
+ }
+ else
+ {
+ state.buttons[i] = false;
+ }
+ }
+
+ state.connected = true;
+ }
+
+ return state;
+}
+
+
+////////////////////////////////////////////////////////////
+BOOL CALLBACK JoystickImpl::deviceEnumerationCallback(const DIDEVICEINSTANCE* deviceInstance, void*)
+{
+ for (std::size_t i = 0; i < joystickList.size(); ++i)
+ {
+ if (joystickList[i].guid == deviceInstance->guidInstance)
+ {
+ joystickList[i].plugged = true;
+
+ return DIENUM_CONTINUE;
+ }
+ }
+
+ JoystickRecord record = { deviceInstance->guidInstance, sf::Joystick::Count, true };
+ joystickList.push_back(record);
+
+ return DIENUM_CONTINUE;
+}
+
+
+////////////////////////////////////////////////////////////
+BOOL CALLBACK JoystickImpl::deviceObjectEnumerationCallback(const DIDEVICEOBJECTINSTANCE* deviceObjectInstance, void* userData)
+{
+ sf::priv::JoystickImpl& joystick = *reinterpret_cast<sf::priv::JoystickImpl*>(userData);
+
+ if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_AXIS)
+ {
+ // Axes
+ if (deviceObjectInstance->guidType == guids::GUID_XAxis)
+ joystick.m_axes[Joystick::X] = DIJOFS_X;
+ else if (deviceObjectInstance->guidType == guids::GUID_YAxis)
+ joystick.m_axes[Joystick::Y] = DIJOFS_Y;
+ else if (deviceObjectInstance->guidType == guids::GUID_ZAxis)
+ joystick.m_axes[Joystick::Z] = DIJOFS_Z;
+ else if (deviceObjectInstance->guidType == guids::GUID_RzAxis)
+ joystick.m_axes[Joystick::R] = DIJOFS_RZ;
+ else if (deviceObjectInstance->guidType == guids::GUID_RxAxis)
+ joystick.m_axes[Joystick::U] = DIJOFS_RX;
+ else if (deviceObjectInstance->guidType == guids::GUID_RyAxis)
+ joystick.m_axes[Joystick::V] = DIJOFS_RY;
+ else if (deviceObjectInstance->guidType == guids::GUID_Slider)
+ {
+ if(joystick.m_axes[Joystick::U] == -1)
+ joystick.m_axes[Joystick::U] = DIJOFS_SLIDER(0);
+ else
+ joystick.m_axes[Joystick::V] = DIJOFS_SLIDER(1);
+ }
+ else
+ return DIENUM_CONTINUE;
+
+ // Set the axis' value range to that of a signed short: [-32768, 32767]
+ DIPROPRANGE propertyRange;
+
+ std::memset(&propertyRange, 0, sizeof(propertyRange));
+ propertyRange.diph.dwSize = sizeof(propertyRange);
+ propertyRange.diph.dwHeaderSize = sizeof(propertyRange.diph);
+ propertyRange.diph.dwObj = deviceObjectInstance->dwType;
+ propertyRange.diph.dwHow = DIPH_BYID;
+ propertyRange.lMin = -32768;
+ propertyRange.lMax = 32767;
+
+ HRESULT result = joystick.m_device->SetProperty(DIPROP_RANGE, &propertyRange.diph);
+
+ if (result)
+ err() << "Failed to set DirectInput device axis property range: " << result << std::endl;
+
+ return DIENUM_CONTINUE;
+ }
+ else if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_POV)
+ {
+ // POVs
+ if (deviceObjectInstance->guidType == guids::GUID_POV)
+ {
+ if (joystick.m_axes[Joystick::PovX] == -1)
+ {
+ joystick.m_axes[Joystick::PovX] = DIJOFS_POV(0);
+ joystick.m_axes[Joystick::PovY] = DIJOFS_POV(0);
+ }
+ }
+
+ return DIENUM_CONTINUE;
+ }
+ else if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_BUTTON)
+ {
+ // Buttons
+ for (int i = 0; i < Joystick::ButtonCount; ++i)
+ {
+ if (joystick.m_buttons[i] == -1)
+ {
+ joystick.m_buttons[i] = DIJOFS_BUTTON(i);
+ break;
+ }
+ }
+
+ return DIENUM_CONTINUE;
+ }
+
+ return DIENUM_CONTINUE;
+}
+
} // namespace priv
} // namespace sf
diff --git a/src/SFML/Window/Win32/JoystickImpl.hpp b/src/SFML/Window/Win32/JoystickImpl.hpp
index 570634a..8affc27 100644
--- a/src/SFML/Window/Win32/JoystickImpl.hpp
+++ b/src/SFML/Window/Win32/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -34,13 +34,15 @@
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
-#define _WIN32_WINDOWS 0x0501
-#define _WIN32_WINNT 0x0501
+#define _WIN32_WINDOWS 0x0501
+#define _WIN32_WINNT 0x0501
+#define DIRECTINPUT_VERSION 0x0800
#include <SFML/Window/Joystick.hpp>
#include <SFML/Window/JoystickImpl.hpp>
#include <SFML/System/String.hpp>
#include <windows.h>
#include <mmsystem.h>
+#include <dinput.h>
namespace sf
@@ -78,6 +80,20 @@ public:
static bool isConnected(unsigned int index);
////////////////////////////////////////////////////////////
+ /// \brief Enable or disable lazy enumeration updates
+ ///
+ /// \param status Whether to rely on windows triggering enumeration updates
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setLazyUpdates(bool status);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the connection status of all joysticks
+ ///
+ ////////////////////////////////////////////////////////////
+ static void updateConnections();
+
+ ////////////////////////////////////////////////////////////
/// \brief Open the joystick
///
/// \param index Index assigned to the joystick
@@ -117,14 +133,100 @@ public:
////////////////////////////////////////////////////////////
JoystickState update();
+ ////////////////////////////////////////////////////////////
+ /// \brief Perform the global initialization of the joystick module (DInput)
+ ///
+ ////////////////////////////////////////////////////////////
+ static void initializeDInput();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Perform the global cleanup of the joystick module (DInput)
+ ///
+ ////////////////////////////////////////////////////////////
+ static void cleanupDInput();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Check if a joystick is currently connected (DInput)
+ ///
+ /// \param index Index of the joystick to check
+ ///
+ /// \return True if the joystick is connected, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool isConnectedDInput(unsigned int index);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the connection status of all joysticks (DInput)
+ ///
+ ////////////////////////////////////////////////////////////
+ static void updateConnectionsDInput();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Open the joystick (DInput)
+ ///
+ /// \param index Index assigned to the joystick
+ ///
+ /// \return True on success, false on failure
+ ///
+ ////////////////////////////////////////////////////////////
+ bool openDInput(unsigned int index);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Close the joystick (DInput)
+ ///
+ ////////////////////////////////////////////////////////////
+ void closeDInput();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the joystick capabilities (DInput)
+ ///
+ /// \return Joystick capabilities
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickCaps getCapabilitiesDInput() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the joystick and get its new state (DInput)
+ ///
+ /// \return Joystick state
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickState updateDInput();
+
private:
////////////////////////////////////////////////////////////
+ /// \brief Device enumeration callback function passed to EnumDevices in updateConnections
+ ///
+ /// \param deviceInstance Device object instance
+ /// \param userData User data (unused)
+ ///
+ /// \return DIENUM_CONTINUE to continue enumerating devices or DIENUM_STOP to stop
+ ///
+ ////////////////////////////////////////////////////////////
+ static BOOL CALLBACK deviceEnumerationCallback(const DIDEVICEINSTANCE* deviceInstance, void* userData);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Device object enumeration callback function passed to EnumObjects in open
+ ///
+ /// \param deviceObjectInstance Device object instance
+ /// \param userData User data (pointer to our JoystickImpl object)
+ ///
+ /// \return DIENUM_CONTINUE to continue enumerating objects or DIENUM_STOP to stop
+ ///
+ ////////////////////////////////////////////////////////////
+ static BOOL CALLBACK deviceObjectEnumerationCallback(const DIDEVICEOBJECTINSTANCE* deviceObjectInstance, void* userData);
+
+ ////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- unsigned int m_index; ///< Index of the joystick
- JOYCAPS m_caps; ///< Joystick capabilities
- Joystick::Identification m_identification; ///< Joystick identification
+ unsigned int m_index; ///< Index of the joystick
+ JOYCAPS m_caps; ///< Joystick capabilities
+ IDirectInputDevice8W* m_device; ///< DirectInput 8.x device
+ DIDEVCAPS m_deviceCaps; ///< DirectInput device capabilities
+ int m_axes[Joystick::AxisCount]; ///< Offsets to the bytes containing the axes states, -1 if not available
+ int m_buttons[Joystick::ButtonCount]; ///< Offsets to the bytes containing the button states, -1 if not available
+ Joystick::Identification m_identification; ///< Joystick identification
};
} // namespace priv
diff --git a/src/SFML/Window/Win32/SensorImpl.cpp b/src/SFML/Window/Win32/SensorImpl.cpp
index 4c00668..3496265 100644
--- a/src/SFML/Window/Win32/SensorImpl.cpp
+++ b/src/SFML/Window/Win32/SensorImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/SensorImpl.hpp b/src/SFML/Window/Win32/SensorImpl.hpp
index 747220a..e8b618e 100644
--- a/src/SFML/Window/Win32/SensorImpl.hpp
+++ b/src/SFML/Window/Win32/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/VideoModeImpl.cpp b/src/SFML/Window/Win32/VideoModeImpl.cpp
index 8783931..71ad671 100644
--- a/src/SFML/Window/Win32/VideoModeImpl.cpp
+++ b/src/SFML/Window/Win32/VideoModeImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -42,6 +42,7 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
// Enumerate all available video modes for the primary display adapter
DEVMODE win32Mode;
win32Mode.dmSize = sizeof(win32Mode);
+ win32Mode.dmDriverExtra = 0;
for (int count = 0; EnumDisplaySettings(NULL, count, &win32Mode); ++count)
{
// Convert to sf::VideoMode
@@ -61,6 +62,7 @@ VideoMode VideoModeImpl::getDesktopMode()
{
DEVMODE win32Mode;
win32Mode.dmSize = sizeof(win32Mode);
+ win32Mode.dmDriverExtra = 0;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &win32Mode);
return VideoMode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel);
diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp
index 3e07c48..fd9f89e 100644
--- a/src/SFML/Window/Win32/WglContext.cpp
+++ b/src/SFML/Window/Win32/WglContext.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -154,6 +154,9 @@ m_ownsWindow (false)
////////////////////////////////////////////////////////////
WglContext::~WglContext()
{
+ // Notify unshared OpenGL resources of context destruction
+ cleanupUnsharedResources();
+
// Destroy the OpenGL context
if (m_context)
{
diff --git a/src/SFML/Window/Win32/WglContext.hpp b/src/SFML/Window/Win32/WglContext.hpp
index d45de78..d692605 100644
--- a/src/SFML/Window/Win32/WglContext.hpp
+++ b/src/SFML/Window/Win32/WglContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/WglExtensions.cpp b/src/SFML/Window/Win32/WglExtensions.cpp
index 3c037ab..b96271b 100644
--- a/src/SFML/Window/Win32/WglExtensions.cpp
+++ b/src/SFML/Window/Win32/WglExtensions.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/WglExtensions.hpp b/src/SFML/Window/Win32/WglExtensions.hpp
index a5400cf..3cefd99 100644
--- a/src/SFML/Window/Win32/WglExtensions.hpp
+++ b/src/SFML/Window/Win32/WglExtensions.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/Win32/WglExtensions.txt b/src/SFML/Window/Win32/WglExtensions.txt
index 667c853..fa61675 100644
--- a/src/SFML/Window/Win32/WglExtensions.txt
+++ b/src/SFML/Window/Win32/WglExtensions.txt
@@ -10,4 +10,4 @@ WGL_ARB_multisample
WGL_ARB_pixel_format
WGL_ARB_pbuffer
WGL_ARB_create_context
-WGL_ARB_create_context_profile \ No newline at end of file
+WGL_ARB_create_context_profile
diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp
index a6c723e..e8e17fe 100644..100755
--- a/src/SFML/Window/Win32/WindowImplWin32.cpp
+++ b/src/SFML/Window/Win32/WindowImplWin32.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -39,7 +39,12 @@
#include <GL/gl.h>
#include <SFML/System/Err.hpp>
#include <SFML/System/Utf.hpp>
+// dbt.h is lowercase here, as a cross-compile on linux with mingw-w64
+// expects lowercase, and a native compile on windows, whether via msvc
+// or mingw-w64 addresses files in a case insensitive manner.
+#include <dbt.h>
#include <vector>
+#include <cstring>
// MinGW lacks the definition of some Win32 constants
#ifndef XBUTTON1
@@ -55,13 +60,15 @@
#define MAPVK_VK_TO_VSC (0)
#endif
-
namespace
{
- unsigned int windowCount = 0;
+ unsigned int windowCount = 0; // Windows owned by SFML
+ unsigned int handleCount = 0; // All window handles
const wchar_t* className = L"SFML_Window";
sf::priv::WindowImplWin32* fullscreenWindow = NULL;
+ const GUID GUID_DEVINTERFACE_HID = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}};
+
void setProcessDpiAware()
{
// Try SetProcessDpiAwareness first
@@ -126,7 +133,8 @@ namespace priv
WindowImplWin32::WindowImplWin32(WindowHandle handle) :
m_handle (handle),
m_callback (0),
-m_cursor (NULL),
+m_cursorVisible (true), // might need to call GetCursorInfo
+m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
m_icon (NULL),
m_keyRepeatEnabled(true),
m_lastSize (0, 0),
@@ -141,6 +149,12 @@ m_cursorGrabbed (false)
if (m_handle)
{
+ // If we're the first window handle, we only need to poll for joysticks when WM_DEVICECHANGE message is received
+ if (handleCount == 0)
+ JoystickImpl::setLazyUpdates(true);
+
+ ++handleCount;
+
// We change the event procedure of the control (it is important to save the old one)
SetWindowLongPtrW(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
m_callback = SetWindowLongPtrW(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WindowImplWin32::globalOnEvent));
@@ -152,14 +166,15 @@ m_cursorGrabbed (false)
WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
m_handle (NULL),
m_callback (0),
-m_cursor (NULL),
+m_cursorVisible (true), // might need to call GetCursorInfo
+m_lastCursor (LoadCursor(NULL, IDC_ARROW)),
m_icon (NULL),
m_keyRepeatEnabled(true),
m_lastSize (mode.width, mode.height),
m_resizing (false),
m_surrogate (0),
m_mouseInside (false),
-m_fullscreen (style & Style::Fullscreen),
+m_fullscreen ((style & Style::Fullscreen) != 0),
m_cursorGrabbed (m_fullscreen)
{
// Set that this process is DPI aware and can handle DPI scaling
@@ -202,6 +217,19 @@ m_cursorGrabbed (m_fullscreen)
// Create the window
m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
+ // Register to receive device interface change notifications (used for joystick connection handling)
+ DEV_BROADCAST_DEVICEINTERFACE deviceInterface = {sizeof(DEV_BROADCAST_DEVICEINTERFACE), DBT_DEVTYP_DEVICEINTERFACE, 0, GUID_DEVINTERFACE_HID, 0};
+ RegisterDeviceNotification(m_handle, &deviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
+
+ // If we're the first window handle, we only need to poll for joysticks when WM_DEVICECHANGE message is received
+ if (m_handle)
+ {
+ if (handleCount == 0)
+ JoystickImpl::setLazyUpdates(true);
+
+ ++handleCount;
+ }
+
// By default, the OS limits the size of the window the the desktop size,
// we have to resize it after creation to apply the real size
setSize(Vector2u(mode.width, mode.height));
@@ -218,10 +246,21 @@ m_cursorGrabbed (m_fullscreen)
////////////////////////////////////////////////////////////
WindowImplWin32::~WindowImplWin32()
{
+ // TODO should we restore the cursor shape and visibility?
+
// Destroy the custom icon, if any
if (m_icon)
DestroyIcon(m_icon);
+ // If it's the last window handle we have to poll for joysticks again
+ if (m_handle)
+ {
+ --handleCount;
+
+ if (handleCount == 0)
+ JoystickImpl::setLazyUpdates(false);
+ }
+
if (!m_callback)
{
// Destroy the window
@@ -360,12 +399,14 @@ void WindowImplWin32::setVisible(bool visible)
////////////////////////////////////////////////////////////
void WindowImplWin32::setMouseCursorVisible(bool visible)
{
- if (visible)
- m_cursor = LoadCursorW(NULL, IDC_ARROW);
- else
- m_cursor = NULL;
-
- SetCursor(m_cursor);
+ // Don't call twice ShowCursor with the same parameter value;
+ // we don't want to increment/decrement the internal counter
+ // more than once.
+ if (visible != m_cursorVisible)
+ {
+ m_cursorVisible = visible;
+ ShowCursor(visible);
+ }
}
@@ -378,6 +419,14 @@ void WindowImplWin32::setMouseCursorGrabbed(bool grabbed)
////////////////////////////////////////////////////////////
+void WindowImplWin32::setMouseCursor(const CursorImpl& cursor)
+{
+ m_lastCursor = cursor.m_cursor;
+ SetCursor(m_lastCursor);
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
{
m_keyRepeatEnabled = enabled;
@@ -538,7 +587,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
// The mouse has moved, if the cursor is in our window we must refresh the cursor
if (LOWORD(lParam) == HTCLIENT)
- SetCursor(m_cursor);
+ SetCursor(m_lastCursor);
break;
}
@@ -684,10 +733,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
Event event;
event.type = Event::KeyPressed;
- event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+ event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0;
+ event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0;
+ event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0;
+ event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN));
event.key.code = virtualKeyCodeToSF(wParam, lParam);
pushEvent(event);
}
@@ -700,10 +749,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
Event event;
event.type = Event::KeyReleased;
- event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+ event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0;
+ event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0;
+ event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0;
+ event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN));
event.key.code = virtualKeyCodeToSF(wParam, lParam);
pushEvent(event);
break;
@@ -936,6 +985,20 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
pushEvent(event);
break;
}
+ case WM_DEVICECHANGE:
+ {
+ // Some sort of device change has happened, update joystick connections
+ if ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE))
+ {
+ // Some sort of device change has happened, update joystick connections if it is a device interface
+ DEV_BROADCAST_HDR* deviceBroadcastHeader = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
+
+ if (deviceBroadcastHeader && (deviceBroadcastHeader->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
+ JoystickImpl::updateConnections();
+ }
+
+ break;
+ }
}
}
@@ -963,21 +1026,21 @@ Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags)
case VK_LWIN: return Keyboard::LSystem;
case VK_RWIN: return Keyboard::RSystem;
case VK_APPS: return Keyboard::Menu;
- case VK_OEM_1: return Keyboard::SemiColon;
+ case VK_OEM_1: return Keyboard::Semicolon;
case VK_OEM_2: return Keyboard::Slash;
case VK_OEM_PLUS: return Keyboard::Equal;
- case VK_OEM_MINUS: return Keyboard::Dash;
+ case VK_OEM_MINUS: return Keyboard::Hyphen;
case VK_OEM_4: return Keyboard::LBracket;
case VK_OEM_6: return Keyboard::RBracket;
case VK_OEM_COMMA: return Keyboard::Comma;
case VK_OEM_PERIOD: return Keyboard::Period;
case VK_OEM_7: return Keyboard::Quote;
- case VK_OEM_5: return Keyboard::BackSlash;
+ case VK_OEM_5: return Keyboard::Backslash;
case VK_OEM_3: return Keyboard::Tilde;
case VK_ESCAPE: return Keyboard::Escape;
case VK_SPACE: return Keyboard::Space;
- case VK_RETURN: return Keyboard::Return;
- case VK_BACK: return Keyboard::BackSpace;
+ case VK_RETURN: return Keyboard::Enter;
+ case VK_BACK: return Keyboard::Backspace;
case VK_TAB: return Keyboard::Tab;
case VK_PRIOR: return Keyboard::PageUp;
case VK_NEXT: return Keyboard::PageDown;
diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp
index 6c29e0b..4114c51 100644..100755
--- a/src/SFML/Window/Win32/WindowImplWin32.hpp
+++ b/src/SFML/Window/Win32/WindowImplWin32.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -154,6 +154,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
@@ -266,7 +274,8 @@ private:
////////////////////////////////////////////////////////////
HWND m_handle; ///< Win32 handle of the window
LONG_PTR m_callback; ///< Stores the original event callback function of the control
- HCURSOR m_cursor; ///< The system cursor to display into the window
+ bool m_cursorVisible; ///< Is the cursor visible or hidden?
+ HCURSOR m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
HICON m_icon; ///< Custom icon assigned to the window
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
Vector2u m_lastSize; ///< The last handled size of the window
diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp
index 6618e5b..b1ed548 100644
--- a/src/SFML/Window/Window.cpp
+++ b/src/SFML/Window/Window.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -297,6 +297,14 @@ void Window::setMouseCursorGrabbed(bool grabbed)
////////////////////////////////////////////////////////////
+void Window::setMouseCursor(const Cursor& cursor)
+{
+ if (m_impl)
+ m_impl->setMouseCursor(cursor.getImpl());
+}
+
+
+////////////////////////////////////////////////////////////
void Window::setKeyRepeatEnabled(bool enabled)
{
if (m_impl)
diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp
index f258aca..3de404a 100644
--- a/src/SFML/Window/WindowImpl.cpp
+++ b/src/SFML/Window/WindowImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -38,7 +38,7 @@
#include <SFML/Window/Win32/WindowImplWin32.hpp>
typedef sf::priv::WindowImplWin32 WindowImplType;
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
+#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) || defined(SFML_SYSTEM_OPENBSD)
#include <SFML/Window/Unix/WindowImplX11.hpp>
typedef sf::priv::WindowImplX11 WindowImplType;
@@ -86,7 +86,10 @@ m_joystickThreshold(0.1f)
// Get the initial joystick states
JoystickManager::getInstance().update();
for (unsigned int i = 0; i < Joystick::Count; ++i)
+ {
m_joystickStates[i] = JoystickManager::getInstance().getState(i);
+ std::fill_n(m_previousAxes[i], static_cast<std::size_t>(Joystick::AxisCount), 0.f);
+ }
// Get the initial sensor states
for (unsigned int i = 0; i < Sensor::Count; ++i)
@@ -176,6 +179,10 @@ void WindowImpl::processJoystickEvents()
event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected;
event.joystickButton.joystickId = i;
pushEvent(event);
+
+ // Clear previous axes positions
+ if (connected)
+ std::fill_n(m_previousAxes[i], static_cast<std::size_t>(Joystick::AxisCount), 0.f);
}
if (connected)
@@ -186,7 +193,7 @@ void WindowImpl::processJoystickEvents()
if (caps.axes[j])
{
Joystick::Axis axis = static_cast<Joystick::Axis>(j);
- float prevPos = previousState.axes[axis];
+ float prevPos = m_previousAxes[i][axis];
float currPos = m_joystickStates[i].axes[axis];
if (fabs(currPos - prevPos) >= m_joystickThreshold)
{
@@ -196,6 +203,8 @@ void WindowImpl::processJoystickEvents()
event.joystickMove.axis = axis;
event.joystickMove.position = currPos;
pushEvent(event);
+
+ m_previousAxes[i][axis] = currPos;
}
}
}
diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp
index 96f4436..a360a01 100644
--- a/src/SFML/Window/WindowImpl.hpp
+++ b/src/SFML/Window/WindowImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -31,6 +31,8 @@
#include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/String.hpp>
+#include <SFML/Window/ContextSettings.hpp>
+#include <SFML/Window/CursorImpl.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Window/Joystick.hpp>
#include <SFML/Window/JoystickImpl.hpp>
@@ -38,7 +40,7 @@
#include <SFML/Window/SensorImpl.hpp>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/WindowHandle.hpp>
-#include <SFML/Window/ContextSettings.hpp>
+#include <SFML/Window/Window.hpp>
#include <queue>
#include <set>
@@ -195,6 +197,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed) = 0;
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor) = 0;
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
@@ -260,10 +270,11 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- std::queue<Event> m_events; ///< Queue of available events
- JoystickState m_joystickStates[Joystick::Count]; ///< Previous state of the joysticks
- Vector3f m_sensorValue[Sensor::Count]; ///< Previous value of the sensors
- float m_joystickThreshold; ///< Joystick threshold (minimum motion for "move" event to be generated)
+ std::queue<Event> m_events; ///< Queue of available events
+ JoystickState m_joystickStates[Joystick::Count]; ///< Previous state of the joysticks
+ Vector3f m_sensorValue[Sensor::Count]; ///< Previous value of the sensors
+ float m_joystickThreshold; ///< Joystick threshold (minimum motion for "move" event to be generated)
+ float m_previousAxes[Joystick::Count][Joystick::AxisCount]; ///< Position of each axis last time a move event triggered, in range [-100, 100]
};
} // namespace priv
diff --git a/src/SFML/Window/iOS/ClipboardImpl.hpp b/src/SFML/Window/iOS/ClipboardImpl.hpp
new file mode 100644
index 0000000..f89d5a9
--- /dev/null
+++ b/src/SFML/Window/iOS/ClipboardImpl.hpp
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CLIPBOARDIMPLIOS_HPP
+#define SFML_CLIPBOARDIMPLIOS_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/String.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+/// \brief Give access to the system clipboard
+///
+////////////////////////////////////////////////////////////
+class ClipboardImpl
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the content of the clipboard as string data
+ ///
+ /// This function returns the content of the clipboard
+ /// as a string. If the clipboard does not contain string
+ /// it returns an empty sf::String object.
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static String getString();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Set the content of the clipboard as string data
+ ///
+ /// This function sets the content of the clipboard as a
+ /// string.
+ ///
+ /// \param text sf::String object containing the data to be sent
+ /// to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ static void setString(const String& text);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_CLIPBOARDIMPLIOS_HPP
+
diff --git a/src/SFML/Window/iOS/ClipboardImpl.mm b/src/SFML/Window/iOS/ClipboardImpl.mm
new file mode 100644
index 0000000..641e16c
--- /dev/null
+++ b/src/SFML/Window/iOS/ClipboardImpl.mm
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/iOS/ClipboardImpl.hpp>
+
+#import <UIKit/UIKit.h>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getString()
+{
+ UIPasteboard* pboard = [UIPasteboard generalPasteboard];
+ if (pboard.hasStrings)
+ {
+ NSString* data = pboard.string;
+
+ char const* utf8 = [data cStringUsingEncoding:NSUTF8StringEncoding];
+ NSUInteger length = [data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+
+ return String::fromUtf8(utf8, utf8 + length);
+ }
+ else
+ {
+ return String();
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ std::basic_string<Uint8> utf8 = text.toUtf8();
+ NSString* data = [[NSString alloc] initWithBytes:utf8.data()
+ length:utf8.length()
+ encoding:NSUTF8StringEncoding];
+
+ UIPasteboard* pboard = [UIPasteboard generalPasteboard];
+ pboard.string = data;
+}
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/iOS/CursorImpl.cpp b/src/SFML/Window/iOS/CursorImpl.cpp
new file mode 100644
index 0000000..a886f32
--- /dev/null
+++ b/src/SFML/Window/iOS/CursorImpl.cpp
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/iOS/CursorImpl.hpp>
+
+namespace sf
+{
+namespace priv
+{
+
+////////////////////////////////////////////////////////////
+CursorImpl::CursorImpl()
+{
+ // Nothing.
+}
+
+
+////////////////////////////////////////////////////////////
+CursorImpl::~CursorImpl()
+{
+ // Nothing.
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
+{
+ // Not supported
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool CursorImpl::loadFromSystem(Cursor::Type type)
+{
+ // Not supported
+ return false;
+}
+
+
+} // namespace priv
+
+} // namespace sf
+
diff --git a/src/SFML/Window/iOS/CursorImpl.hpp b/src/SFML/Window/iOS/CursorImpl.hpp
new file mode 100644
index 0000000..9d1dbfc
--- /dev/null
+++ b/src/SFML/Window/iOS/CursorImpl.hpp
@@ -0,0 +1,88 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. 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 notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_CURSORIMPLIOS_HPP
+#define SFML_CURSORIMPLIOS_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Cursor.hpp>
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Vector2.hpp>
+
+
+namespace sf
+{
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief iOS implementation of Cursor
+///
+/// This is a typical "not supported" implementation.
+///
+////////////////////////////////////////////////////////////
+class CursorImpl : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Refer to sf::Cursor::Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ /// Refer to sf::Cursor::~Cursor().
+ ///
+ ////////////////////////////////////////////////////////////
+ ~CursorImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a cursor with the provided image
+ ///
+ /// Returns false.
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create a native system cursor
+ ///
+ /// Returns false.
+ ///
+ ////////////////////////////////////////////////////////////
+ bool loadFromSystem(Cursor::Type type);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+#endif // SFML_CURSORIMPLIOS_HPP
diff --git a/src/SFML/Window/iOS/EaglContext.hpp b/src/SFML/Window/iOS/EaglContext.hpp
index a6853ee..7121f2e 100644
--- a/src/SFML/Window/iOS/EaglContext.hpp
+++ b/src/SFML/Window/iOS/EaglContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/EaglContext.mm b/src/SFML/Window/iOS/EaglContext.mm
index 72cec77..9fd6b83 100644
--- a/src/SFML/Window/iOS/EaglContext.mm
+++ b/src/SFML/Window/iOS/EaglContext.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -91,6 +91,9 @@ m_clock ()
////////////////////////////////////////////////////////////
EaglContext::~EaglContext()
{
+ // Notify unshared OpenGL resources of context destruction
+ cleanupUnsharedResources();
+
if (m_context)
{
// Activate the context, so that we can destroy the buffers
diff --git a/src/SFML/Window/iOS/InputImpl.hpp b/src/SFML/Window/iOS/InputImpl.hpp
index f41e072..0d62071 100644
--- a/src/SFML/Window/iOS/InputImpl.hpp
+++ b/src/SFML/Window/iOS/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/InputImpl.mm b/src/SFML/Window/iOS/InputImpl.mm
index 6ac604f..bada27d 100644
--- a/src/SFML/Window/iOS/InputImpl.mm
+++ b/src/SFML/Window/iOS/InputImpl.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/JoystickImpl.hpp b/src/SFML/Window/iOS/JoystickImpl.hpp
index 9e4f52f..e9fc8bd 100644
--- a/src/SFML/Window/iOS/JoystickImpl.hpp
+++ b/src/SFML/Window/iOS/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/JoystickImpl.mm b/src/SFML/Window/iOS/JoystickImpl.mm
index 4f4de86..47fa8d3 100644
--- a/src/SFML/Window/iOS/JoystickImpl.mm
+++ b/src/SFML/Window/iOS/JoystickImpl.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/ObjCType.hpp b/src/SFML/Window/iOS/ObjCType.hpp
index cf93a19..5d06c51 100644
--- a/src/SFML/Window/iOS/ObjCType.hpp
+++ b/src/SFML/Window/iOS/ObjCType.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFAppDelegate.hpp b/src/SFML/Window/iOS/SFAppDelegate.hpp
index 984e1e1..e389655 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.hpp
+++ b/src/SFML/Window/iOS/SFAppDelegate.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm
index 5e202d3..6b17384 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.mm
+++ b/src/SFML/Window/iOS/SFAppDelegate.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFMain.hpp b/src/SFML/Window/iOS/SFMain.hpp
index dffd107..4d0b5b4 100644
--- a/src/SFML/Window/iOS/SFMain.hpp
+++ b/src/SFML/Window/iOS/SFMain.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFMain.mm b/src/SFML/Window/iOS/SFMain.mm
index 7a48cdb..4e9910a 100644
--- a/src/SFML/Window/iOS/SFMain.mm
+++ b/src/SFML/Window/iOS/SFMain.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFView.hpp b/src/SFML/Window/iOS/SFView.hpp
index d858a2b..f3f4276 100644
--- a/src/SFML/Window/iOS/SFView.hpp
+++ b/src/SFML/Window/iOS/SFView.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFView.mm b/src/SFML/Window/iOS/SFView.mm
index b4ae496..063c61a 100644
--- a/src/SFML/Window/iOS/SFView.mm
+++ b/src/SFML/Window/iOS/SFView.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFViewController.hpp b/src/SFML/Window/iOS/SFViewController.hpp
index 65b6eda..b8a77aa 100644
--- a/src/SFML/Window/iOS/SFViewController.hpp
+++ b/src/SFML/Window/iOS/SFViewController.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SFViewController.mm b/src/SFML/Window/iOS/SFViewController.mm
index 582b3ff..d8be047 100644
--- a/src/SFML/Window/iOS/SFViewController.mm
+++ b/src/SFML/Window/iOS/SFViewController.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SensorImpl.hpp b/src/SFML/Window/iOS/SensorImpl.hpp
index 88d995e..05c6b93 100644
--- a/src/SFML/Window/iOS/SensorImpl.hpp
+++ b/src/SFML/Window/iOS/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/SensorImpl.mm b/src/SFML/Window/iOS/SensorImpl.mm
index 02f8e1f..249c41a 100644
--- a/src/SFML/Window/iOS/SensorImpl.mm
+++ b/src/SFML/Window/iOS/SensorImpl.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/VideoModeImpl.mm b/src/SFML/Window/iOS/VideoModeImpl.mm
index 6798afe..7296d9d 100644
--- a/src/SFML/Window/iOS/VideoModeImpl.mm
+++ b/src/SFML/Window/iOS/VideoModeImpl.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
diff --git a/src/SFML/Window/iOS/WindowImplUIKit.hpp b/src/SFML/Window/iOS/WindowImplUIKit.hpp
index 51e890a..60e0407 100644
--- a/src/SFML/Window/iOS/WindowImplUIKit.hpp
+++ b/src/SFML/Window/iOS/WindowImplUIKit.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -158,6 +158,14 @@ public:
virtual void setMouseCursorGrabbed(bool grabbed);
////////////////////////////////////////////////////////////
+ /// \brief Set the displayed cursor to a native system cursor
+ ///
+ /// \param cursor Native system cursor type to display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursor(const CursorImpl& cursor);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
diff --git a/src/SFML/Window/iOS/WindowImplUIKit.mm b/src/SFML/Window/iOS/WindowImplUIKit.mm
index 49791ce..35337db 100644
--- a/src/SFML/Window/iOS/WindowImplUIKit.mm
+++ b/src/SFML/Window/iOS/WindowImplUIKit.mm
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -191,6 +191,13 @@ void WindowImplUIKit::setMouseCursorGrabbed(bool grabbed)
////////////////////////////////////////////////////////////
+void WindowImplUIKit::setMouseCursor(const CursorImpl& cursor)
+{
+ // Not applicable
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplUIKit::setKeyRepeatEnabled(bool enabled)
{
// Not applicable
diff --git a/tools/android/compile_libs.sh b/tools/android/compile_libs.sh
index fa833fc..deadac5 100755
--- a/tools/android/compile_libs.sh
+++ b/tools/android/compile_libs.sh
@@ -48,12 +48,6 @@ rm $DESTDIR/$1/usr/lib/libFLAC*.so*
cd $LOCALDIR/build/libvorbis-* && sed -i 's/-version-info/-avoid-version/g' lib/Makefile.in lib/Makefile.am && ./configure $HOST $PREFIX --enable-shared=no && make && make install
rm $DESTDIR/$1/usr/lib/libvorbis*.so*
-# Compile libsndfile (important: --disable-sqlite)
-cd $LOCALDIR/build/libsndfile-* && sed -i 's/-version-info/-avoid-version/g' src/Makefile.in src/Makefile.am && ./configure $HOST $PREFIX --disable-sqlite && make && make install
-
-# Compile JPEG
-cd $LOCALDIR/build/jpeg-* && sed -i 's/-version-info/-avoid-version/g' Makefile.in Makefile.am && ./configure $HOST $PREFIX && make && make install
-
# Compile freetype
cd $LOCALDIR/build/freetype-* && sed -i 's/-version-info/-avoid-version/g' builds/unix/unix-cc.in && ./configure $HOST $PREFIX && make && make install
diff --git a/tools/android/download_sources.sh b/tools/android/download_sources.sh
index b85e776..27c75eb 100755
--- a/tools/android/download_sources.sh
+++ b/tools/android/download_sources.sh
@@ -11,9 +11,6 @@ OGG=libogg-$OGG_VERSION
SNDFILE_VERSION=1.0.25
SNDFILE=libsndfile-$SNDFILE_VERSION
-JPEG_VERSION=9
-JPEG=jpeg-$JPEG_VERSION
-
FREETYPE_VERSION=2.4.0
FREETYPE=freetype-$FREETYPE_VERSION
@@ -37,18 +34,6 @@ then
tar -C build -xf src/$OGG.tar.gz
fi
-wget -nc -P src http://www.mega-nerd.com/libsndfile/files/$SNDFILE.tar.gz
-if [ ! -d "$PWD/tmp/$SNDFILE" ]
-then
- tar -C build -xf src/$SNDFILE.tar.gz
-fi
-
-wget -nc -P src http://www.ijg.org/files/jpegsrc.v$JPEG_VERSION.tar.gz
-if [ ! -d "$PWD/tmp/$JPEG" ]
-then
- tar -C build -xf src/jpegsrc.v$JPEG_VERSION.tar.gz
-fi
-
wget -nc -P src http://download.savannah.gnu.org/releases/freetype/$FREETYPE.tar.gz
if [ ! -d "$PWD/tmp/$FREETYPE" ]
then
diff --git a/tools/pkg-config/sfml-audio.pc.in b/tools/pkg-config/sfml-audio.pc.in
index 7456daa..0d7a3ce 100644
--- a/tools/pkg-config/sfml-audio.pc.in
+++ b/tools/pkg-config/sfml-audio.pc.in
@@ -8,5 +8,8 @@ Description: The Simple and Fast Multimedia Library, audio module.
URL: http://www.sfml-dev.org
Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
Requires: sfml-system
+Requires.private: openal, vorbisenc, vorbisfile, vorbis, ogg, flac
Libs: -L${libdir} -lsfml-audio
+# openal may be a system framework
+Libs.private: @OPENAL_LIBRARY@
Cflags: -I${includedir}
diff --git a/tools/pkg-config/sfml-graphics.pc.in b/tools/pkg-config/sfml-graphics.pc.in
index d0a88a1..b138160 100644
--- a/tools/pkg-config/sfml-graphics.pc.in
+++ b/tools/pkg-config/sfml-graphics.pc.in
@@ -8,5 +8,8 @@ Description: The Simple and Fast Multimedia Library, graphics module.
URL: http://www.sfml-dev.org
Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
Requires: sfml-window
+Requires.private: sfml-system, freetype2
Libs: -L${libdir} -lsfml-graphics
+# gl may not be in pkg-config
+Libs.private: @OPENGL_gl_LIBRARY@ @OPENGL_glu_LIBRARY@
Cflags: -I${includedir}
diff --git a/tools/pkg-config/sfml-window.pc.in b/tools/pkg-config/sfml-window.pc.in
index b0266e6..93bf344 100644
--- a/tools/pkg-config/sfml-window.pc.in
+++ b/tools/pkg-config/sfml-window.pc.in
@@ -9,4 +9,6 @@ URL: http://www.sfml-dev.org
Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
Requires: sfml-system
Libs: -L${libdir} -lsfml-window
+# gl may not be in pkg-config
+Libs.private: @OPENGL_gl_LIBRARY@ @OPENGL_glu_LIBRARY@
Cflags: -I${includedir}